mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-04 03:50:30 +08:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d52058d2ae | ||
![]() |
bcfbfc6947 | ||
![]() |
75699c4a26 | ||
![]() |
3e8bfb52a8 | ||
![]() |
bbbd857a45 | ||
![]() |
498900df76 | ||
![]() |
7e3c1a6581 | ||
![]() |
6e28043dba | ||
![]() |
cb200687dc | ||
![]() |
23bb0ee450 | ||
![]() |
117259dfc5 | ||
![]() |
e71d0476f0 | ||
![]() |
b5d26767b2 | ||
![]() |
5c4e22288e | ||
![]() |
3ac4be64b8 | ||
![]() |
97db54b6b9 | ||
![]() |
3a19d4c7c8 | ||
![]() |
a60be2b2ab | ||
![]() |
06ef97a080 | ||
![]() |
167c1b0f1b | ||
![]() |
7d0eae230e | ||
![]() |
901867e8bb | ||
![]() |
b7be1943fa | ||
![]() |
bbbda1982f | ||
![]() |
e593f5be5b | ||
![]() |
0918757e85 | ||
![]() |
ce0d45a70b |
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -127,7 +127,7 @@ jobs:
|
|||||||
release-and-push:
|
release-and-push:
|
||||||
name: Release And Push
|
name: Release And Push
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casbin/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
||||||
needs: [ frontend, backend, linter, e2e ]
|
needs: [ frontend, backend, linter, e2e ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -182,14 +182,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Push to Docker Hub
|
- name: Push to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: STANDARD
|
target: STANDARD
|
||||||
@@ -199,7 +199,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Push All In One Version to Docker Hub
|
- name: Push All In One Version to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: ALLINONE
|
target: ALLINONE
|
||||||
|
2
.github/workflows/sync.yml
vendored
2
.github/workflows/sync.yml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
synchronize-with-crowdin:
|
synchronize-with-crowdin:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casbin/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
@@ -87,8 +87,7 @@ https://casdoor.org/docs/category/integrations
|
|||||||
## How to contact?
|
## How to contact?
|
||||||
|
|
||||||
- Discord: https://discord.gg/5rPsrAzK7S
|
- Discord: https://discord.gg/5rPsrAzK7S
|
||||||
- Forum: https://forum.casbin.com
|
- Contact: https://casdoor.org/help
|
||||||
- Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
|
@@ -51,7 +51,8 @@ p, *, *, GET, /api/get-account, *, *
|
|||||||
p, *, *, GET, /api/userinfo, *, *
|
p, *, *, GET, /api/userinfo, *, *
|
||||||
p, *, *, GET, /api/user, *, *
|
p, *, *, GET, /api/user, *, *
|
||||||
p, *, *, GET, /api/health, *, *
|
p, *, *, GET, /api/health, *, *
|
||||||
p, *, *, POST, /api/webhook, *, *
|
p, *, *, *, /api/webhook, *, *
|
||||||
|
p, *, *, GET, /api/get-qrcode, *, *
|
||||||
p, *, *, GET, /api/get-webhook-event, *, *
|
p, *, *, GET, /api/get-webhook-event, *, *
|
||||||
p, *, *, GET, /api/get-captcha-status, *, *
|
p, *, *, GET, /api/get-captcha-status, *, *
|
||||||
p, *, *, *, /api/login/oauth, *, *
|
p, *, *, *, /api/login/oauth, *, *
|
||||||
@@ -80,6 +81,7 @@ p, *, *, *, /.well-known/jwks, *, *
|
|||||||
p, *, *, GET, /api/get-saml-login, *, *
|
p, *, *, GET, /api/get-saml-login, *, *
|
||||||
p, *, *, POST, /api/acs, *, *
|
p, *, *, POST, /api/acs, *, *
|
||||||
p, *, *, GET, /api/saml/metadata, *, *
|
p, *, *, GET, /api/saml/metadata, *, *
|
||||||
|
p, *, *, *, /api/saml/redirect, *, *
|
||||||
p, *, *, *, /cas, *, *
|
p, *, *, *, /cas, *, *
|
||||||
p, *, *, *, /scim, *, *
|
p, *, *, *, /scim, *, *
|
||||||
p, *, *, *, /api/webauthn, *, *
|
p, *, *, *, /api/webauthn, *, *
|
||||||
@@ -95,6 +97,7 @@ p, *, *, GET, /api/get-organization-names, *, *
|
|||||||
p, *, *, GET, /api/get-all-objects, *, *
|
p, *, *, GET, /api/get-all-objects, *, *
|
||||||
p, *, *, GET, /api/get-all-actions, *, *
|
p, *, *, GET, /api/get-all-actions, *, *
|
||||||
p, *, *, GET, /api/get-all-roles, *, *
|
p, *, *, GET, /api/get-all-roles, *, *
|
||||||
|
p, *, *, GET, /api/get-invitation-info, *, *
|
||||||
`
|
`
|
||||||
|
|
||||||
sa := stringadapter.NewAdapter(ruleText)
|
sa := stringadapter.NewAdapter(ruleText)
|
||||||
@@ -150,7 +153,7 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
|||||||
|
|
||||||
func isAllowedInDemoMode(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
func isAllowedInDemoMode(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
||||||
if method == "POST" {
|
if method == "POST" {
|
||||||
if strings.HasPrefix(urlPath, "/api/login") || urlPath == "/api/logout" || urlPath == "/api/signup" || urlPath == "/api/callback" || urlPath == "/api/send-verification-code" || urlPath == "/api/send-email" || urlPath == "/api/verify-captcha" || urlPath == "/api/verify-code" || urlPath == "/api/check-user-password" || strings.HasPrefix(urlPath, "/api/mfa/") {
|
if strings.HasPrefix(urlPath, "/api/login") || urlPath == "/api/logout" || urlPath == "/api/signup" || urlPath == "/api/callback" || urlPath == "/api/send-verification-code" || urlPath == "/api/send-email" || urlPath == "/api/verify-captcha" || urlPath == "/api/verify-code" || urlPath == "/api/check-user-password" || strings.HasPrefix(urlPath, "/api/mfa/") || urlPath == "/api/webhook" || urlPath == "/api/get-qrcode" {
|
||||||
return true
|
return true
|
||||||
} else if urlPath == "/api/update-user" {
|
} else if urlPath == "/api/update-user" {
|
||||||
// Allow ordinary users to update their own information
|
// Allow ordinary users to update their own information
|
||||||
|
14
conf/conf.go
14
conf/conf.go
@@ -71,7 +71,10 @@ func GetConfigInt64(key string) (int64, error) {
|
|||||||
|
|
||||||
func GetConfigDataSourceName() string {
|
func GetConfigDataSourceName() string {
|
||||||
dataSourceName := GetConfigString("dataSourceName")
|
dataSourceName := GetConfigString("dataSourceName")
|
||||||
|
return ReplaceDataSourceNameByDocker(dataSourceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReplaceDataSourceNameByDocker(dataSourceName string) string {
|
||||||
runningInDocker := os.Getenv("RUNNING_IN_DOCKER")
|
runningInDocker := os.Getenv("RUNNING_IN_DOCKER")
|
||||||
if runningInDocker == "true" {
|
if runningInDocker == "true" {
|
||||||
// https://stackoverflow.com/questions/48546124/what-is-linux-equivalent-of-host-docker-internal
|
// https://stackoverflow.com/questions/48546124/what-is-linux-equivalent-of-host-docker-internal
|
||||||
@@ -81,7 +84,6 @@ func GetConfigDataSourceName() string {
|
|||||||
dataSourceName = strings.ReplaceAll(dataSourceName, "localhost", "host.docker.internal")
|
dataSourceName = strings.ReplaceAll(dataSourceName, "localhost", "host.docker.internal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSourceName
|
return dataSourceName
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,13 +110,3 @@ func GetConfigBatchSize() int {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigRealDataSourceName(driverName string) string {
|
|
||||||
var dataSourceName string
|
|
||||||
if driverName != "mysql" {
|
|
||||||
dataSourceName = GetConfigDataSourceName()
|
|
||||||
} else {
|
|
||||||
dataSourceName = GetConfigDataSourceName() + GetConfigString("dbName")
|
|
||||||
}
|
|
||||||
return dataSourceName
|
|
||||||
}
|
|
||||||
|
@@ -93,6 +93,10 @@ func (c *ApiController) Signup() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if application == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !application.EnableSignUp {
|
if !application.EnableSignUp {
|
||||||
c.ResponseError(c.T("account:The application does not allow to sign up new account"))
|
c.ResponseError(c.T("account:The application does not allow to sign up new account"))
|
||||||
@@ -105,6 +109,11 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if organization == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:The organization: %s does not exist"), authForm.Organization))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
|
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
@@ -227,7 +236,7 @@ func (c *ApiController) Signup() {
|
|||||||
|
|
||||||
if invitation != nil {
|
if invitation != nil {
|
||||||
invitation.UsedCount += 1
|
invitation.UsedCount += 1
|
||||||
_, err := object.UpdateInvitation(invitation.GetId(), invitation)
|
_, err := object.UpdateInvitation(invitation.GetId(), invitation, c.GetAcceptLanguage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@@ -19,12 +19,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/captcha"
|
"github.com/casdoor/casdoor/captcha"
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
@@ -37,11 +36,6 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
wechatScanType string
|
|
||||||
lock sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func codeToResponse(code *object.Code) *Response {
|
func codeToResponse(code *object.Code) *Response {
|
||||||
if code.Code == "" {
|
if code.Code == "" {
|
||||||
return &Response{Status: "error", Msg: code.Message, Data: code.Code}
|
return &Response{Status: "error", Msg: code.Message, Data: code.Code}
|
||||||
@@ -896,6 +890,7 @@ func (c *ApiController) GetSamlLogin() {
|
|||||||
authURL, method, err := object.GenerateSamlRequest(providerId, relayState, c.Ctx.Request.Host, c.GetAcceptLanguage())
|
authURL, method, err := object.GenerateSamlRequest(providerId, relayState, c.Ctx.Request.Host, c.GetAcceptLanguage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
c.ResponseOk(authURL, method)
|
c.ResponseOk(authURL, method)
|
||||||
}
|
}
|
||||||
@@ -906,62 +901,126 @@ func (c *ApiController) HandleSamlLogin() {
|
|||||||
decode, err := base64.StdEncoding.DecodeString(relayState)
|
decode, err := base64.StdEncoding.DecodeString(relayState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
slice := strings.Split(string(decode), "&")
|
slice := strings.Split(string(decode), "&")
|
||||||
relayState = url.QueryEscape(relayState)
|
relayState = url.QueryEscape(relayState)
|
||||||
samlResponse = url.QueryEscape(samlResponse)
|
samlResponse = url.QueryEscape(samlResponse)
|
||||||
targetUrl := fmt.Sprintf("%s?relayState=%s&samlResponse=%s",
|
targetUrl := fmt.Sprintf("%s?relayState=%s&samlResponse=%s",
|
||||||
slice[4], relayState, samlResponse)
|
slice[4], relayState, samlResponse)
|
||||||
c.Redirect(targetUrl, 303)
|
c.Redirect(targetUrl, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleOfficialAccountEvent ...
|
// HandleOfficialAccountEvent ...
|
||||||
// @Tag System API
|
// @Tag System API
|
||||||
// @Title HandleOfficialAccountEvent
|
// @Title HandleOfficialAccountEvent
|
||||||
// @router /webhook [POST]
|
// @router /webhook [POST]
|
||||||
// @Success 200 {object} object.Userinfo The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
func (c *ApiController) HandleOfficialAccountEvent() {
|
func (c *ApiController) HandleOfficialAccountEvent() {
|
||||||
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
if c.Ctx.Request.Method == "GET" {
|
||||||
|
s := c.Ctx.Request.FormValue("echostr")
|
||||||
|
echostr, _ := strconv.Atoi(s)
|
||||||
|
c.SetData(echostr)
|
||||||
|
c.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respBytes, err := io.ReadAll(c.Ctx.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
signature := c.Input().Get("signature")
|
||||||
|
timestamp := c.Input().Get("timestamp")
|
||||||
|
nonce := c.Input().Get("nonce")
|
||||||
var data struct {
|
var data struct {
|
||||||
MsgType string `xml:"MsgType"`
|
MsgType string `xml:"MsgType"`
|
||||||
Event string `xml:"Event"`
|
Event string `xml:"Event"`
|
||||||
EventKey string `xml:"EventKey"`
|
EventKey string `xml:"EventKey"`
|
||||||
|
FromUserName string `xml:"FromUserName"`
|
||||||
|
Ticket string `xml:"Ticket"`
|
||||||
}
|
}
|
||||||
err = xml.Unmarshal(respBytes, &data)
|
err = xml.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if strings.ToUpper(data.Event) != "SCAN" && strings.ToUpper(data.Event) != "SUBSCRIBE" {
|
||||||
lock.Lock()
|
|
||||||
defer lock.Unlock()
|
|
||||||
if data.EventKey != "" {
|
|
||||||
wechatScanType = data.Event
|
|
||||||
c.Ctx.WriteString("")
|
c.Ctx.WriteString("")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if data.Ticket == "" {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
providerId := data.EventKey
|
||||||
|
provider, err := object.GetProvider(providerId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if data.Ticket == "" {
|
||||||
|
c.ResponseError("empty ticket")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !idp.VerifyWechatSignature(provider.Content, nonce, timestamp, signature) {
|
||||||
|
c.ResponseError("invalid signature")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idp.Lock.Lock()
|
||||||
|
if idp.WechatCacheMap == nil {
|
||||||
|
idp.WechatCacheMap = make(map[string]idp.WechatCacheMapValue)
|
||||||
|
}
|
||||||
|
idp.WechatCacheMap[data.Ticket] = idp.WechatCacheMapValue{
|
||||||
|
IsScanned: true,
|
||||||
|
WechatUnionId: data.FromUserName,
|
||||||
|
}
|
||||||
|
idp.Lock.Unlock()
|
||||||
|
|
||||||
|
c.Ctx.WriteString("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWebhookEventType ...
|
// GetWebhookEventType ...
|
||||||
// @Tag System API
|
// @Tag System API
|
||||||
// @Title GetWebhookEventType
|
// @Title GetWebhookEventType
|
||||||
// @router /get-webhook-event [GET]
|
// @router /get-webhook-event [GET]
|
||||||
// @Success 200 {object} object.Userinfo The Response object
|
// @Param ticket query string true "The eventId of QRCode"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
func (c *ApiController) GetWebhookEventType() {
|
func (c *ApiController) GetWebhookEventType() {
|
||||||
lock.Lock()
|
ticket := c.Input().Get("ticket")
|
||||||
defer lock.Unlock()
|
|
||||||
resp := &Response{
|
idp.Lock.RLock()
|
||||||
Status: "ok",
|
_, ok := idp.WechatCacheMap[ticket]
|
||||||
Msg: "",
|
idp.Lock.RUnlock()
|
||||||
Data: wechatScanType,
|
if !ok {
|
||||||
|
c.ResponseError("ticket not found")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
c.Data["json"] = resp
|
|
||||||
wechatScanType = ""
|
c.ResponseOk("SCAN", ticket)
|
||||||
c.ServeJSON()
|
}
|
||||||
|
|
||||||
|
// GetQRCode
|
||||||
|
// @Tag System API
|
||||||
|
// @Title GetWechatQRCode
|
||||||
|
// @router /get-qrcode [GET]
|
||||||
|
// @Param id query string true "The id ( owner/name ) of provider"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
|
func (c *ApiController) GetQRCode() {
|
||||||
|
providerId := c.Input().Get("id")
|
||||||
|
provider, err := object.GetProvider(providerId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
code, ticket, err := idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2, providerId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(code, ticket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCaptchaStatus
|
// GetCaptchaStatus
|
||||||
|
@@ -121,6 +121,10 @@ func (c *ApiController) Enforce() {
|
|||||||
}
|
}
|
||||||
} else if owner != "" {
|
} else if owner != "" {
|
||||||
permissions, err = object.GetPermissions(owner)
|
permissions, err = object.GetPermissions(owner)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
@@ -235,6 +239,10 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
}
|
}
|
||||||
} else if owner != "" {
|
} else if owner != "" {
|
||||||
permissions, err = object.GetPermissions(owner)
|
permissions, err = object.GetPermissions(owner)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
|
@@ -84,6 +84,32 @@ func (c *ApiController) GetInvitation() {
|
|||||||
c.ResponseOk(invitation)
|
c.ResponseOk(invitation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetInvitationCodeInfo
|
||||||
|
// @Title GetInvitationCodeInfo
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description get invitation code information
|
||||||
|
// @Param code query string true "Invitation code"
|
||||||
|
// @Success 200 {object} object.Invitation The Response object
|
||||||
|
// @router /get-invitation-info [get]
|
||||||
|
func (c *ApiController) GetInvitationCodeInfo() {
|
||||||
|
code := c.Input().Get("code")
|
||||||
|
applicationId := c.Input().Get("applicationId")
|
||||||
|
|
||||||
|
application, err := object.GetApplication(applicationId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
invitation, msg := object.GetInvitationByCode(code, application.Organization, c.GetAcceptLanguage())
|
||||||
|
if msg != "" {
|
||||||
|
c.ResponseError(msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(object.GetMaskedInvitation(invitation))
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateInvitation
|
// UpdateInvitation
|
||||||
// @Title UpdateInvitation
|
// @Title UpdateInvitation
|
||||||
// @Tag Invitation API
|
// @Tag Invitation API
|
||||||
@@ -102,7 +128,7 @@ func (c *ApiController) UpdateInvitation() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.UpdateInvitation(id, &invitation))
|
c.Data["json"] = wrapActionResponse(object.UpdateInvitation(id, &invitation, c.GetAcceptLanguage()))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +147,7 @@ func (c *ApiController) AddInvitation() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddInvitation(&invitation))
|
c.Data["json"] = wrapActionResponse(object.AddInvitation(&invitation, c.GetAcceptLanguage()))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,14 @@ import (
|
|||||||
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MfaRecoveryCodesSession = "mfa_recovery_codes"
|
||||||
|
MfaCountryCodeSession = "mfa_country_code"
|
||||||
|
MfaDestSession = "mfa_dest"
|
||||||
|
MfaTotpSecretSession = "mfa_totp_secret"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MfaSetupInitiate
|
// MfaSetupInitiate
|
||||||
@@ -57,12 +65,20 @@ func (c *ApiController) MfaSetupInitiate() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mfaProps, err := MfaUtil.Initiate(c.Ctx, user.GetId())
|
mfaProps, err := MfaUtil.Initiate(user.GetId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recoveryCode := uuid.NewString()
|
||||||
|
c.SetSession(MfaRecoveryCodesSession, recoveryCode)
|
||||||
|
if mfaType == object.TotpType {
|
||||||
|
c.SetSession(MfaTotpSecretSession, mfaProps.Secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
mfaProps.RecoveryCodes = []string{recoveryCode}
|
||||||
|
|
||||||
resp := mfaProps
|
resp := mfaProps
|
||||||
c.ResponseOk(resp)
|
c.ResponseOk(resp)
|
||||||
}
|
}
|
||||||
@@ -83,13 +99,39 @@ func (c *ApiController) MfaSetupVerify() {
|
|||||||
c.ResponseError("missing auth type or passcode")
|
c.ResponseError("missing auth type or passcode")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mfaUtil := object.GetMfaUtil(mfaType, nil)
|
|
||||||
|
config := &object.MfaProps{
|
||||||
|
MfaType: mfaType,
|
||||||
|
}
|
||||||
|
if mfaType == object.TotpType {
|
||||||
|
secret := c.GetSession(MfaTotpSecretSession)
|
||||||
|
if secret == nil {
|
||||||
|
c.ResponseError("totp secret is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.Secret = secret.(string)
|
||||||
|
} else if mfaType == object.EmailType || mfaType == object.SmsType {
|
||||||
|
dest := c.GetSession(MfaDestSession)
|
||||||
|
if dest == nil {
|
||||||
|
c.ResponseError("destination is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.Secret = dest.(string)
|
||||||
|
countryCode := c.GetSession(MfaCountryCodeSession)
|
||||||
|
if countryCode == nil {
|
||||||
|
c.ResponseError("country code is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.CountryCode = countryCode.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
mfaUtil := object.GetMfaUtil(mfaType, config)
|
||||||
if mfaUtil == nil {
|
if mfaUtil == nil {
|
||||||
c.ResponseError("Invalid multi-factor authentication type")
|
c.ResponseError("Invalid multi-factor authentication type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := mfaUtil.SetupVerify(c.Ctx, passcode)
|
err := mfaUtil.SetupVerify(passcode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
} else {
|
} else {
|
||||||
@@ -122,18 +164,58 @@ func (c *ApiController) MfaSetupEnable() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mfaUtil := object.GetMfaUtil(mfaType, nil)
|
config := &object.MfaProps{
|
||||||
|
MfaType: mfaType,
|
||||||
|
}
|
||||||
|
|
||||||
|
if mfaType == object.TotpType {
|
||||||
|
secret := c.GetSession(MfaTotpSecretSession)
|
||||||
|
if secret == nil {
|
||||||
|
c.ResponseError("totp secret is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.Secret = secret.(string)
|
||||||
|
} else if mfaType == object.EmailType || mfaType == object.SmsType {
|
||||||
|
dest := c.GetSession(MfaDestSession)
|
||||||
|
if dest == nil {
|
||||||
|
c.ResponseError("destination is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.Secret = dest.(string)
|
||||||
|
countryCode := c.GetSession(MfaCountryCodeSession)
|
||||||
|
if countryCode == nil {
|
||||||
|
c.ResponseError("country code is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.CountryCode = countryCode.(string)
|
||||||
|
}
|
||||||
|
recoveryCodes := c.GetSession(MfaRecoveryCodesSession)
|
||||||
|
if recoveryCodes == nil {
|
||||||
|
c.ResponseError("recovery codes is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.RecoveryCodes = []string{recoveryCodes.(string)}
|
||||||
|
|
||||||
|
mfaUtil := object.GetMfaUtil(mfaType, config)
|
||||||
if mfaUtil == nil {
|
if mfaUtil == nil {
|
||||||
c.ResponseError("Invalid multi-factor authentication type")
|
c.ResponseError("Invalid multi-factor authentication type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mfaUtil.Enable(c.Ctx, user)
|
err = mfaUtil.Enable(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.DelSession(MfaRecoveryCodesSession)
|
||||||
|
if mfaType == object.TotpType {
|
||||||
|
c.DelSession(MfaTotpSecretSession)
|
||||||
|
} else {
|
||||||
|
c.DelSession(MfaCountryCodeSession)
|
||||||
|
c.DelSession(MfaDestSession)
|
||||||
|
}
|
||||||
|
|
||||||
c.ResponseOk(http.StatusText(http.StatusOK))
|
c.ResponseOk(http.StatusText(http.StatusOK))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
)
|
)
|
||||||
@@ -34,7 +35,13 @@ func (c *ApiController) GetSamlMeta() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata, err := object.GetSamlMeta(application, host)
|
enablePostBinding, err := c.GetBool("enablePostBinding", false)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata, err := object.GetSamlMeta(application, host, enablePostBinding)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -43,3 +50,17 @@ func (c *ApiController) GetSamlMeta() {
|
|||||||
c.Data["xml"] = metadata
|
c.Data["xml"] = metadata
|
||||||
c.ServeXML()
|
c.ServeXML()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) HandleSamlRedirect() {
|
||||||
|
host := c.Ctx.Request.Host
|
||||||
|
|
||||||
|
owner := c.Ctx.Input.Param(":owner")
|
||||||
|
application := c.Ctx.Input.Param(":application")
|
||||||
|
|
||||||
|
relayState := c.Input().Get("RelayState")
|
||||||
|
samlRequest := c.Input().Get("SAMLRequest")
|
||||||
|
|
||||||
|
targetURL := object.GetSamlRedirectAddress(owner, application, relayState, samlRequest, host)
|
||||||
|
|
||||||
|
c.Redirect(targetURL, http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
@@ -47,6 +47,11 @@ func (c *ApiController) GetSystemInfo() {
|
|||||||
// @router /get-version-info [get]
|
// @router /get-version-info [get]
|
||||||
func (c *ApiController) GetVersionInfo() {
|
func (c *ApiController) GetVersionInfo() {
|
||||||
versionInfo, err := util.GetVersionInfo()
|
versionInfo, err := util.GetVersionInfo()
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if versionInfo.Version != "" {
|
if versionInfo.Version != "" {
|
||||||
c.ResponseOk(versionInfo)
|
c.ResponseOk(versionInfo)
|
||||||
return
|
return
|
||||||
|
@@ -156,6 +156,10 @@ func (c *ApiController) GetUser() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if userFromUserId == nil {
|
||||||
|
c.ResponseOk(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
||||||
}
|
}
|
||||||
|
@@ -161,7 +161,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
vform.Dest = mfaProps.Secret
|
vform.Dest = mfaProps.Secret
|
||||||
}
|
}
|
||||||
} else if vform.Method == MfaSetupVerification {
|
} else if vform.Method == MfaSetupVerification {
|
||||||
c.SetSession(object.MfaDestSession, vform.Dest)
|
c.SetSession(MfaDestSession, vform.Dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := application.GetEmailProvider()
|
provider, err := application.GetEmailProvider()
|
||||||
@@ -198,8 +198,8 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if vform.Method == MfaSetupVerification {
|
if vform.Method == MfaSetupVerification {
|
||||||
c.SetSession(object.MfaCountryCodeSession, vform.CountryCode)
|
c.SetSession(MfaCountryCodeSession, vform.CountryCode)
|
||||||
c.SetSession(object.MfaDestSession, vform.Dest)
|
c.SetSession(MfaDestSession, vform.Dest)
|
||||||
}
|
}
|
||||||
} else if vform.Method == MfaAuthVerification {
|
} else if vform.Method == MfaAuthVerification {
|
||||||
mfaProps := user.GetPreferredMfaProps(false)
|
mfaProps := user.GetPreferredMfaProps(false)
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
|
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
|
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
|
||||||
"DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname",
|
"DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname",
|
||||||
"Email already exists": "E-Mail existiert bereits",
|
"Email already exists": "E-Mail existiert bereits",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Afiliación no puede estar en blanco",
|
"Affiliation cannot be blank": "Afiliación no puede estar en blanco",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
|
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
|
||||||
"DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido",
|
"DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido",
|
||||||
"Email already exists": "El correo electrónico ya existe",
|
"Email already exists": "El correo electrónico ya existe",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation ne peut pas être vide",
|
"Affiliation cannot be blank": "Affiliation ne peut pas être vide",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
|
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
|
||||||
"DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide",
|
"DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide",
|
||||||
"Email already exists": "E-mail déjà existant",
|
"Email already exists": "E-mail déjà existant",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
|
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
|
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
|
||||||
"DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid",
|
"DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid",
|
||||||
"Email already exists": "Email sudah ada",
|
"Email already exists": "Email sudah ada",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "所属は空白にできません",
|
"Affiliation cannot be blank": "所属は空白にできません",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "表示名は空白にできません",
|
"DisplayName cannot be blank": "表示名は空白にできません",
|
||||||
"DisplayName is not valid real name": "表示名は有効な実名ではありません",
|
"DisplayName is not valid real name": "表示名は有効な実名ではありません",
|
||||||
"Email already exists": "メールは既に存在します",
|
"Email already exists": "メールは既に存在します",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
|
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
|
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
|
||||||
"DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다",
|
"DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다",
|
||||||
"Email already exists": "이메일이 이미 존재합니다",
|
"Email already exists": "이메일이 이미 존재합니다",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
|
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Имя отображения не может быть пустым",
|
"DisplayName cannot be blank": "Имя отображения не может быть пустым",
|
||||||
"DisplayName is not valid real name": "DisplayName не является действительным именем",
|
"DisplayName is not valid real name": "DisplayName не является действительным именем",
|
||||||
"Email already exists": "Электронная почта уже существует",
|
"Email already exists": "Электронная почта уже существует",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
|
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Tên hiển thị không thể để trống",
|
"DisplayName cannot be blank": "Tên hiển thị không thể để trống",
|
||||||
"DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ",
|
"DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ",
|
||||||
"Email already exists": "Email đã tồn tại",
|
"Email already exists": "Email đã tồn tại",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "工作单位不可为空",
|
"Affiliation cannot be blank": "工作单位不可为空",
|
||||||
|
"Default code does not match the code's matching rules": "邀请码默认值和邀请码规则不匹配",
|
||||||
"DisplayName cannot be blank": "显示名称不可为空",
|
"DisplayName cannot be blank": "显示名称不可为空",
|
||||||
"DisplayName is not valid real name": "显示名称必须是真实姓名",
|
"DisplayName is not valid real name": "显示名称必须是真实姓名",
|
||||||
"Email already exists": "该邮箱已存在",
|
"Email already exists": "该邮箱已存在",
|
||||||
@@ -37,9 +38,9 @@
|
|||||||
"Email is invalid": "无效邮箱",
|
"Email is invalid": "无效邮箱",
|
||||||
"Empty username.": "用户名不可为空",
|
"Empty username.": "用户名不可为空",
|
||||||
"FirstName cannot be blank": "名不可以为空",
|
"FirstName cannot be blank": "名不可以为空",
|
||||||
"Invitation code cannot be blank": "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 is invalid": "邀请码无效",
|
||||||
"Invitation code suspended": "邀请码已被禁止使用",
|
"Invitation code suspended": "邀请码已被禁止使用",
|
||||||
"LDAP user name or password incorrect": "LDAP密码错误",
|
"LDAP user name or password incorrect": "LDAP密码错误",
|
||||||
"LastName cannot be blank": "姓不可以为空",
|
"LastName cannot be blank": "姓不可以为空",
|
||||||
|
@@ -121,6 +121,9 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var respKeys struct {
|
var respKeys struct {
|
||||||
Keys []interface{} `json:"keys"`
|
Keys []interface{} `json:"keys"`
|
||||||
}
|
}
|
||||||
|
@@ -75,6 +75,7 @@ import (
|
|||||||
"github.com/markbates/goth/providers/twitterv2"
|
"github.com/markbates/goth/providers/twitterv2"
|
||||||
"github.com/markbates/goth/providers/typetalk"
|
"github.com/markbates/goth/providers/typetalk"
|
||||||
"github.com/markbates/goth/providers/uber"
|
"github.com/markbates/goth/providers/uber"
|
||||||
|
"github.com/markbates/goth/providers/vk"
|
||||||
"github.com/markbates/goth/providers/wepay"
|
"github.com/markbates/goth/providers/wepay"
|
||||||
"github.com/markbates/goth/providers/xero"
|
"github.com/markbates/goth/providers/xero"
|
||||||
"github.com/markbates/goth/providers/yahoo"
|
"github.com/markbates/goth/providers/yahoo"
|
||||||
@@ -371,6 +372,11 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
Provider: uber.New(clientId, clientSecret, redirectUrl),
|
Provider: uber.New(clientId, clientSecret, redirectUrl),
|
||||||
Session: &uber.Session{},
|
Session: &uber.Session{},
|
||||||
}
|
}
|
||||||
|
case "VK":
|
||||||
|
idp = GothIdProvider{
|
||||||
|
Provider: vk.New(clientId, clientSecret, redirectUrl),
|
||||||
|
Session: &vk.Session{},
|
||||||
|
}
|
||||||
case "Wepay":
|
case "Wepay":
|
||||||
idp = GothIdProvider{
|
idp = GothIdProvider{
|
||||||
Provider: wepay.New(clientId, clientSecret, redirectUrl),
|
Provider: wepay.New(clientId, clientSecret, redirectUrl),
|
||||||
|
104
idp/wechat.go
104
idp/wechat.go
@@ -16,25 +16,38 @@ package idp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
WechatCacheMap map[string]WechatCacheMapValue
|
||||||
|
Lock sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
type WeChatIdProvider struct {
|
type WeChatIdProvider struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
Config *oauth2.Config
|
Config *oauth2.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WechatCacheMapValue struct {
|
||||||
|
IsScanned bool
|
||||||
|
WechatUnionId string
|
||||||
|
}
|
||||||
|
|
||||||
func NewWeChatIdProvider(clientId string, clientSecret string, redirectUrl string) *WeChatIdProvider {
|
func NewWeChatIdProvider(clientId string, clientSecret string, redirectUrl string) *WeChatIdProvider {
|
||||||
idp := &WeChatIdProvider{}
|
idp := &WeChatIdProvider{}
|
||||||
|
|
||||||
@@ -77,6 +90,15 @@ type WechatAccessToken struct {
|
|||||||
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||||
// get more detail via: https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
|
// get more detail via: https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
|
||||||
func (idp *WeChatIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
func (idp *WeChatIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
|
if strings.HasPrefix(code, "wechat_oa:") {
|
||||||
|
token := oauth2.Token{
|
||||||
|
AccessToken: code,
|
||||||
|
TokenType: "WeChatAccessToken",
|
||||||
|
Expiry: time.Time{},
|
||||||
|
}
|
||||||
|
return &token, nil
|
||||||
|
}
|
||||||
|
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("grant_type", "authorization_code")
|
params.Add("grant_type", "authorization_code")
|
||||||
params.Add("appid", idp.Config.ClientID)
|
params.Add("appid", idp.Config.ClientID)
|
||||||
@@ -157,6 +179,29 @@ type WechatUserInfo struct {
|
|||||||
func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
var wechatUserInfo WechatUserInfo
|
var wechatUserInfo WechatUserInfo
|
||||||
accessToken := token.AccessToken
|
accessToken := token.AccessToken
|
||||||
|
|
||||||
|
if strings.HasPrefix(accessToken, "wechat_oa:") {
|
||||||
|
Lock.RLock()
|
||||||
|
mapValue, ok := WechatCacheMap[accessToken[10:]]
|
||||||
|
Lock.RUnlock()
|
||||||
|
|
||||||
|
if !ok || mapValue.WechatUnionId == "" {
|
||||||
|
return nil, fmt.Errorf("error ticket")
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock.Lock()
|
||||||
|
delete(WechatCacheMap, accessToken[10:])
|
||||||
|
Lock.Unlock()
|
||||||
|
|
||||||
|
userInfo := UserInfo{
|
||||||
|
Id: mapValue.WechatUnionId,
|
||||||
|
Username: "wx_user_" + mapValue.WechatUnionId,
|
||||||
|
DisplayName: "wx_user_" + mapValue.WechatUnionId,
|
||||||
|
AvatarUrl: "",
|
||||||
|
}
|
||||||
|
return &userInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
openid := token.Extra("Openid")
|
openid := token.Extra("Openid")
|
||||||
|
|
||||||
userInfoUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", accessToken, openid)
|
userInfoUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", accessToken, openid)
|
||||||
@@ -204,60 +249,70 @@ func BuildWechatOpenIdKey(appId string) string {
|
|||||||
return fmt.Sprintf("wechat_openid_%s", appId)
|
return fmt.Sprintf("wechat_openid_%s", appId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, string, error) {
|
||||||
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
||||||
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
resp, err := client.Do(request)
|
resp, err := client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
respBytes, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
ExpireIn int `json:"expires_in"`
|
ExpireIn int `json:"expires_in"`
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
|
ErrCode int `json:"errcode"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(respBytes, &data)
|
err = json.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.AccessToken, nil
|
return data.AccessToken, data.Errmsg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (string, error) {
|
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string, providerId string) (string, string, error) {
|
||||||
accessToken, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
accessToken, errMsg, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg != "" {
|
||||||
|
return "", "", fmt.Errorf("Fail to fetch WeChat QRcode: %s", errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
|
|
||||||
weChatEndpoint := "https://api.weixin.qq.com/cgi-bin/qrcode/create"
|
weChatEndpoint := "https://api.weixin.qq.com/cgi-bin/qrcode/create"
|
||||||
qrCodeUrl := fmt.Sprintf("%s?access_token=%s", weChatEndpoint, accessToken)
|
qrCodeUrl := fmt.Sprintf("%s?access_token=%s", weChatEndpoint, accessToken)
|
||||||
params := `{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}`
|
params := fmt.Sprintf(`{"expire_seconds": 3600, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "%s"}}}`, providerId)
|
||||||
|
|
||||||
bodyData := bytes.NewReader([]byte(params))
|
bodyData := bytes.NewReader([]byte(params))
|
||||||
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Do(requeset)
|
resp, err := client.Do(requeset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
respBytes, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
var data struct {
|
var data struct {
|
||||||
Ticket string `json:"ticket"`
|
Ticket string `json:"ticket"`
|
||||||
@@ -266,11 +321,26 @@ func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (strin
|
|||||||
}
|
}
|
||||||
err = json.Unmarshal(respBytes, &data)
|
err = json.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var png []byte
|
var png []byte
|
||||||
png, err = qrcode.Encode(data.URL, qrcode.Medium, 256)
|
png, err = qrcode.Encode(data.URL, qrcode.Medium, 256)
|
||||||
base64Image := base64.StdEncoding.EncodeToString(png)
|
base64Image := base64.StdEncoding.EncodeToString(png)
|
||||||
return base64Image, nil
|
return base64Image, data.Ticket, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerifyWechatSignature(token string, nonce string, timestamp string, signature string) bool {
|
||||||
|
// verify the signature
|
||||||
|
tmpArr := sort.StringSlice{token, timestamp, nonce}
|
||||||
|
sort.Sort(tmpArr)
|
||||||
|
|
||||||
|
tmpStr := ""
|
||||||
|
for _, str := range tmpArr {
|
||||||
|
tmpStr = tmpStr + str
|
||||||
|
}
|
||||||
|
|
||||||
|
b := sha1.Sum([]byte(tmpStr))
|
||||||
|
res := hex.EncodeToString(b[:])
|
||||||
|
return res == signature
|
||||||
}
|
}
|
||||||
|
@@ -146,7 +146,8 @@
|
|||||||
"isForbidden": false,
|
"isForbidden": false,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"signupApplication": "",
|
"signupApplication": "",
|
||||||
"createdIp": ""
|
"createdIp": "",
|
||||||
|
"groups": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"providers": [
|
"providers": [
|
||||||
@@ -349,5 +350,74 @@
|
|||||||
"owner": "",
|
"owner": "",
|
||||||
"url": ""
|
"url": ""
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name":"",
|
||||||
|
"displayName": "",
|
||||||
|
"manager": "",
|
||||||
|
"contactEmail": "",
|
||||||
|
"type": "",
|
||||||
|
"parent_id": "",
|
||||||
|
"isTopGroup": true,
|
||||||
|
"title": "",
|
||||||
|
"key": "",
|
||||||
|
"children": "",
|
||||||
|
"isEnabled": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"adapters": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"table": "",
|
||||||
|
"useSameDb": true,
|
||||||
|
"type": "",
|
||||||
|
"databaseType": "",
|
||||||
|
"database": "",
|
||||||
|
"host": "",
|
||||||
|
"port": 0,
|
||||||
|
"user": "",
|
||||||
|
"password": "",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"enforcers": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"description": "",
|
||||||
|
"model": "",
|
||||||
|
"adapter": "",
|
||||||
|
"enforcer": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"plans": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"description": "",
|
||||||
|
"price": 0,
|
||||||
|
"currency": "",
|
||||||
|
"period": "",
|
||||||
|
"product": "",
|
||||||
|
"paymentProviders": [],
|
||||||
|
"isEnabled": true,
|
||||||
|
"role", ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pricings": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"description": "",
|
||||||
|
"plans": [],
|
||||||
|
"isEnabled": true,
|
||||||
|
"trialDuration": 0,
|
||||||
|
"application": "",
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
2
main.go
2
main.go
@@ -36,12 +36,12 @@ func main() {
|
|||||||
object.CreateTables()
|
object.CreateTables()
|
||||||
|
|
||||||
object.InitDb()
|
object.InitDb()
|
||||||
object.InitFromFile()
|
|
||||||
object.InitDefaultStorageProvider()
|
object.InitDefaultStorageProvider()
|
||||||
object.InitLdapAutoSynchronizer()
|
object.InitLdapAutoSynchronizer()
|
||||||
proxy.InitHttpClient()
|
proxy.InitHttpClient()
|
||||||
authz.InitApi()
|
authz.InitApi()
|
||||||
object.InitUserManager()
|
object.InitUserManager()
|
||||||
|
object.InitFromFile()
|
||||||
object.InitCasvisorConfig()
|
object.InitCasvisorConfig()
|
||||||
|
|
||||||
util.SafeGoroutine(func() { object.RunSyncUsersJob() })
|
util.SafeGoroutine(func() { object.RunSyncUsersJob() })
|
||||||
|
@@ -178,6 +178,7 @@ func (adapter *Adapter) InitAdapter() error {
|
|||||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataSourceName = conf.ReplaceDataSourceNameByDocker(dataSourceName)
|
||||||
engine, err := xorm.NewEngine(driverName, dataSourceName)
|
engine, err := xorm.NewEngine(driverName, dataSourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/idp"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/xorm-io/core"
|
"github.com/xorm-io/core"
|
||||||
)
|
)
|
||||||
@@ -41,6 +40,15 @@ type SignupItem struct {
|
|||||||
Rule string `json:"rule"`
|
Rule string `json:"rule"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SigninItem struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Visible bool `json:"visible"`
|
||||||
|
Label string `json:"label"`
|
||||||
|
Placeholder string `json:"placeholder"`
|
||||||
|
Rule string `json:"rule"`
|
||||||
|
IsCustom bool `json:"isCustom"`
|
||||||
|
}
|
||||||
|
|
||||||
type SamlItem struct {
|
type SamlItem struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
NameFormat string `json:"nameFormat"`
|
NameFormat string `json:"nameFormat"`
|
||||||
@@ -52,31 +60,33 @@ type Application struct {
|
|||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
Logo string `xorm:"varchar(200)" json:"logo"`
|
Logo string `xorm:"varchar(200)" json:"logo"`
|
||||||
HomepageUrl string `xorm:"varchar(100)" json:"homepageUrl"`
|
HomepageUrl string `xorm:"varchar(100)" json:"homepageUrl"`
|
||||||
Description string `xorm:"varchar(100)" json:"description"`
|
Description string `xorm:"varchar(100)" json:"description"`
|
||||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||||
Cert string `xorm:"varchar(100)" json:"cert"`
|
Cert string `xorm:"varchar(100)" json:"cert"`
|
||||||
EnablePassword bool `json:"enablePassword"`
|
EnablePassword bool `json:"enablePassword"`
|
||||||
EnableSignUp bool `json:"enableSignUp"`
|
EnableSignUp bool `json:"enableSignUp"`
|
||||||
EnableSigninSession bool `json:"enableSigninSession"`
|
EnableSigninSession bool `json:"enableSigninSession"`
|
||||||
EnableAutoSignin bool `json:"enableAutoSignin"`
|
EnableAutoSignin bool `json:"enableAutoSignin"`
|
||||||
EnableCodeSignin bool `json:"enableCodeSignin"`
|
EnableCodeSignin bool `json:"enableCodeSignin"`
|
||||||
EnableSamlCompress bool `json:"enableSamlCompress"`
|
EnableSamlCompress bool `json:"enableSamlCompress"`
|
||||||
EnableSamlC14n10 bool `json:"enableSamlC14n10"`
|
EnableSamlC14n10 bool `json:"enableSamlC14n10"`
|
||||||
EnableWebAuthn bool `json:"enableWebAuthn"`
|
EnableSamlPostBinding bool `json:"enableSamlPostBinding"`
|
||||||
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
|
EnableWebAuthn bool `json:"enableWebAuthn"`
|
||||||
OrgChoiceMode string `json:"orgChoiceMode"`
|
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
|
||||||
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
OrgChoiceMode string `json:"orgChoiceMode"`
|
||||||
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
||||||
SigninMethods []*SigninMethod `xorm:"varchar(2000)" json:"signinMethods"`
|
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
||||||
SignupItems []*SignupItem `xorm:"varchar(2000)" json:"signupItems"`
|
SigninMethods []*SigninMethod `xorm:"varchar(2000)" json:"signinMethods"`
|
||||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
SignupItems []*SignupItem `xorm:"varchar(2000)" json:"signupItems"`
|
||||||
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
SigninItems []*SigninItem `xorm:"mediumtext" json:"signinItems"`
|
||||||
CertPublicKey string `xorm:"-" json:"certPublicKey"`
|
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
||||||
SamlAttributes []*SamlItem `xorm:"varchar(1000)" json:"samlAttributes"`
|
CertPublicKey string `xorm:"-" json:"certPublicKey"`
|
||||||
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
|
SamlAttributes []*SamlItem `xorm:"varchar(1000)" json:"samlAttributes"`
|
||||||
|
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
||||||
@@ -163,15 +173,6 @@ func getProviderMap(owner string) (m map[string]*Provider, err error) {
|
|||||||
|
|
||||||
m = map[string]*Provider{}
|
m = map[string]*Provider{}
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
// Get QRCode only once
|
|
||||||
if provider.Type == "WeChat" && provider.DisableSsl && provider.Content == "" {
|
|
||||||
provider.Content, err = idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
UpdateProvider(provider.Owner+"/"+provider.Name, provider)
|
|
||||||
}
|
|
||||||
|
|
||||||
m[provider.Name] = GetMaskedProvider(provider, true)
|
m[provider.Name] = GetMaskedProvider(provider, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +200,100 @@ func extendApplicationWithOrg(application *Application) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extendApplicationWithSigninItems(application *Application) (err error) {
|
||||||
|
if len(application.SigninItems) == 0 {
|
||||||
|
signinItem := &SigninItem{
|
||||||
|
Name: "Back button",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .back-button {\n top: 65px;\n left: 15px;\n position: absolute;\n }\n</style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Languages",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-languages {\n top: 55px;\n right: 5px;\n position: absolute;\n }\n</style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Logo",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-logo-box {\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "none",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Signin methods",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .signin-methods {\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Username",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-username {\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Password",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-password {\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Agreement",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-agreement {\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Forgot password?",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-forget-password {\n display: inline-flex;\n justify-content: space-between;\n width: 320px;\n margin-bottom: 25px;\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Login button",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-button-box {\n margin-bottom: 5px;\n }\n .login-button {\n width: 100%;\n }\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Signup link",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .login-signup-link {\n margin-bottom: 24px;\n display: flex;\n justify-content: end;\n}\n<style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "None",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
signinItem = &SigninItem{
|
||||||
|
Name: "Providers",
|
||||||
|
Visible: true,
|
||||||
|
Label: "\n<style>\n .provider-img {\n width: 30px;\n margin: 5px;\n }\n .provider-big-img {\n margin-bottom: 10px;\n }\n</style>\n",
|
||||||
|
Placeholder: "",
|
||||||
|
Rule: "Default",
|
||||||
|
}
|
||||||
|
application.SigninItems = append(application.SigninItems, signinItem)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func extendApplicationWithSigninMethods(application *Application) (err error) {
|
func extendApplicationWithSigninMethods(application *Application) (err error) {
|
||||||
if len(application.SigninMethods) == 0 {
|
if len(application.SigninMethods) == 0 {
|
||||||
if application.EnablePassword {
|
if application.EnablePassword {
|
||||||
@@ -249,6 +344,10 @@ func getApplication(owner string, name string) (*Application, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = extendApplicationWithSigninItems(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
@@ -279,6 +378,11 @@ func GetApplicationByOrganizationName(organization string) (*Application, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninItems(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -331,6 +435,11 @@ func GetApplicationByClientId(clientId string) (*Application, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninItems(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
BIN
object/cert.go~
BIN
object/cert.go~
Binary file not shown.
@@ -184,6 +184,15 @@ func CheckInvitationCode(application *Application, organization *Organization, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckInvitationDefaultCode(code string, defaultCode string, lang string) error {
|
||||||
|
if matched, err := util.IsInvitationCodeMatch(code, defaultCode); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !matched {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:Default code does not match the code's matching rules"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func checkSigninErrorTimes(user *User, lang string) error {
|
func checkSigninErrorTimes(user *User, lang string) error {
|
||||||
failedSigninLimit, failedSigninFrozenTime, err := GetFailedSigninConfigByUser(user)
|
failedSigninLimit, failedSigninFrozenTime, err := GetFailedSigninConfigByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -35,6 +35,11 @@ type InitData struct {
|
|||||||
Syncers []*Syncer `json:"syncers"`
|
Syncers []*Syncer `json:"syncers"`
|
||||||
Tokens []*Token `json:"tokens"`
|
Tokens []*Token `json:"tokens"`
|
||||||
Webhooks []*Webhook `json:"webhooks"`
|
Webhooks []*Webhook `json:"webhooks"`
|
||||||
|
Groups []*Group `json:"groups"`
|
||||||
|
Adapters []*Adapter `json:"adapters"`
|
||||||
|
Enforcers []*Enforcer `json:"enforcers"`
|
||||||
|
Plans []*Plan `json:"plans"`
|
||||||
|
Pricings []*Pricing `json:"pricings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitFromFile() {
|
func InitFromFile() {
|
||||||
@@ -94,6 +99,21 @@ func InitFromFile() {
|
|||||||
for _, webhook := range initData.Webhooks {
|
for _, webhook := range initData.Webhooks {
|
||||||
initDefinedWebhook(webhook)
|
initDefinedWebhook(webhook)
|
||||||
}
|
}
|
||||||
|
for _, group := range initData.Groups {
|
||||||
|
initDefinedGroup(group)
|
||||||
|
}
|
||||||
|
for _, adapter := range initData.Adapters {
|
||||||
|
initDefinedAdapter(adapter)
|
||||||
|
}
|
||||||
|
for _, enforcer := range initData.Enforcers {
|
||||||
|
initDefinedEnforcer(enforcer)
|
||||||
|
}
|
||||||
|
for _, plan := range initData.Plans {
|
||||||
|
initDefinedPlan(plan)
|
||||||
|
}
|
||||||
|
for _, pricing := range initData.Pricings {
|
||||||
|
initDefinedPricing(pricing)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +140,11 @@ func readInitDataFromFile(filePath string) (*InitData, error) {
|
|||||||
Syncers: []*Syncer{},
|
Syncers: []*Syncer{},
|
||||||
Tokens: []*Token{},
|
Tokens: []*Token{},
|
||||||
Webhooks: []*Webhook{},
|
Webhooks: []*Webhook{},
|
||||||
|
Groups: []*Group{},
|
||||||
|
Adapters: []*Adapter{},
|
||||||
|
Enforcers: []*Enforcer{},
|
||||||
|
Plans: []*Plan{},
|
||||||
|
Pricings: []*Pricing{},
|
||||||
}
|
}
|
||||||
err := util.JsonToStruct(s, data)
|
err := util.JsonToStruct(s, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -190,7 +215,16 @@ func readInitDataFromFile(filePath string) (*InitData, error) {
|
|||||||
webhook.Headers = []*Header{}
|
webhook.Headers = []*Header{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, plan := range data.Plans {
|
||||||
|
if plan.PaymentProviders == nil {
|
||||||
|
plan.PaymentProviders = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, pricing := range data.Pricings {
|
||||||
|
if pricing.Plans == nil {
|
||||||
|
pricing.Plans = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,3 +468,78 @@ func initDefinedWebhook(webhook *Webhook) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initDefinedGroup(group *Group) {
|
||||||
|
existed, err := getGroup(group.Owner, group.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group.CreatedTime = util.GetCurrentTime()
|
||||||
|
_, err = AddGroup(group)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedAdapter(adapter *Adapter) {
|
||||||
|
existed, err := getAdapter(adapter.Owner, adapter.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
adapter.CreatedTime = util.GetCurrentTime()
|
||||||
|
_, err = AddAdapter(adapter)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedEnforcer(enforcer *Enforcer) {
|
||||||
|
existed, err := getEnforcer(enforcer.Owner, enforcer.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
enforcer.CreatedTime = util.GetCurrentTime()
|
||||||
|
_, err = AddEnforcer(enforcer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedPlan(plan *Plan) {
|
||||||
|
existed, err := getPlan(plan.Owner, plan.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
plan.CreatedTime = util.GetCurrentTime()
|
||||||
|
_, err = AddPlan(plan)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedPricing(pricing *Pricing) {
|
||||||
|
existed, err := getPlan(pricing.Owner, pricing.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pricing.CreatedTime = util.GetCurrentTime()
|
||||||
|
_, err = AddPricing(pricing)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -96,6 +96,31 @@ func writeInitDataToFile(filePath string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groups, err := GetGroups("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
adapters, err := GetAdapters("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
enforcers, err := GetEnforcers("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
plans, err := GetPlans("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pricings, err := GetPricings("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
data := &InitData{
|
data := &InitData{
|
||||||
Organizations: organizations,
|
Organizations: organizations,
|
||||||
Applications: applications,
|
Applications: applications,
|
||||||
@@ -112,6 +137,11 @@ func writeInitDataToFile(filePath string) error {
|
|||||||
Syncers: syncers,
|
Syncers: syncers,
|
||||||
Tokens: tokens,
|
Tokens: tokens,
|
||||||
Webhooks: webhooks,
|
Webhooks: webhooks,
|
||||||
|
Groups: groups,
|
||||||
|
Adapters: adapters,
|
||||||
|
Enforcers: enforcers,
|
||||||
|
Plans: plans,
|
||||||
|
Pricings: pricings,
|
||||||
}
|
}
|
||||||
|
|
||||||
text := util.StructToJsonFormatted(data)
|
text := util.StructToJsonFormatted(data)
|
||||||
|
@@ -40,6 +40,7 @@ type Invitation struct {
|
|||||||
Phone string `xorm:"varchar(100)" json:"phone"`
|
Phone string `xorm:"varchar(100)" json:"phone"`
|
||||||
|
|
||||||
SignupGroup string `xorm:"varchar(100)" json:"signupGroup"`
|
SignupGroup string `xorm:"varchar(100)" json:"signupGroup"`
|
||||||
|
DefaultCode string `xorm:"varchar(100)" json:"defaultCode"`
|
||||||
|
|
||||||
State string `xorm:"varchar(100)" json:"state"`
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
}
|
}
|
||||||
@@ -93,7 +94,45 @@ func GetInvitation(id string) (*Invitation, error) {
|
|||||||
return getInvitation(owner, name)
|
return getInvitation(owner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
func GetInvitationByCode(code string, organizationName string, lang string) (*Invitation, string) {
|
||||||
|
invitations, err := GetInvitations(organizationName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err.Error()
|
||||||
|
}
|
||||||
|
errMsg := ""
|
||||||
|
for _, invitation := range invitations {
|
||||||
|
if isValid, msg := invitation.SimpleCheckInvitationCode(code, lang); isValid {
|
||||||
|
return invitation, msg
|
||||||
|
} else if msg != "" && errMsg == "" {
|
||||||
|
errMsg = msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg != "" {
|
||||||
|
return nil, errMsg
|
||||||
|
} else {
|
||||||
|
return nil, i18n.Translate(lang, "check:Invitation code is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaskedInvitation(invitation *Invitation) *Invitation {
|
||||||
|
if invitation == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
invitation.CreatedTime = ""
|
||||||
|
invitation.UpdatedTime = ""
|
||||||
|
invitation.Code = "***"
|
||||||
|
invitation.DefaultCode = "***"
|
||||||
|
invitation.IsRegexp = false
|
||||||
|
invitation.Quota = -1
|
||||||
|
invitation.UsedCount = -1
|
||||||
|
invitation.SignupGroup = ""
|
||||||
|
|
||||||
|
return invitation
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateInvitation(id string, invitation *Invitation, lang string) (bool, error) {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if p, err := getInvitation(owner, name); err != nil {
|
if p, err := getInvitation(owner, name); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -107,6 +146,11 @@ func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
|||||||
invitation.IsRegexp = isRegexp
|
invitation.IsRegexp = isRegexp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := CheckInvitationDefaultCode(invitation.Code, invitation.DefaultCode, lang)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(invitation)
|
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(invitation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -115,13 +159,18 @@ func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
|||||||
return affected != 0, nil
|
return affected != 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddInvitation(invitation *Invitation) (bool, error) {
|
func AddInvitation(invitation *Invitation, lang string) (bool, error) {
|
||||||
if isRegexp, err := util.IsRegexp(invitation.Code); err != nil {
|
if isRegexp, err := util.IsRegexp(invitation.Code); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else {
|
} else {
|
||||||
invitation.IsRegexp = isRegexp
|
invitation.IsRegexp = isRegexp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := CheckInvitationDefaultCode(invitation.Code, invitation.DefaultCode, lang)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(invitation)
|
affected, err := ormer.Engine.Insert(invitation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -147,7 +196,7 @@ func VerifyInvitation(id string) (payment *Payment, attachInfo map[string]interf
|
|||||||
return nil, nil, fmt.Errorf("the invitation: %s does not exist", id)
|
return nil, nil, fmt.Errorf("the invitation: %s does not exist", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (invitation *Invitation) IsInvitationCodeValid(application *Application, invitationCode string, username string, email string, phone string, lang string) (bool, string) {
|
func (invitation *Invitation) SimpleCheckInvitationCode(invitationCode string, lang string) (bool, string) {
|
||||||
if matched, err := util.IsInvitationCodeMatch(invitation.Code, invitationCode); err != nil {
|
if matched, err := util.IsInvitationCodeMatch(invitation.Code, invitationCode); err != nil {
|
||||||
return false, err.Error()
|
return false, err.Error()
|
||||||
} else if !matched {
|
} else if !matched {
|
||||||
@@ -160,15 +209,6 @@ func (invitation *Invitation) IsInvitationCodeValid(application *Application, in
|
|||||||
if invitation.UsedCount >= invitation.Quota {
|
if invitation.UsedCount >= invitation.Quota {
|
||||||
return false, i18n.Translate(lang, "check:Invitation code exhausted")
|
return false, i18n.Translate(lang, "check:Invitation code exhausted")
|
||||||
}
|
}
|
||||||
if application.IsSignupItemRequired("Username") && invitation.Username != "" && invitation.Username != username {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the username corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
if application.IsSignupItemRequired("Email") && invitation.Email != "" && invitation.Email != email {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the email corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
if application.IsSignupItemRequired("Phone") && invitation.Phone != "" && invitation.Phone != phone {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the phone corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine whether the invitation code is in the form of a regular expression other than pure numbers and letters
|
// Determine whether the invitation code is in the form of a regular expression other than pure numbers and letters
|
||||||
if invitation.IsRegexp {
|
if invitation.IsRegexp {
|
||||||
@@ -179,3 +219,19 @@ func (invitation *Invitation) IsInvitationCodeValid(application *Application, in
|
|||||||
}
|
}
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (invitation *Invitation) IsInvitationCodeValid(application *Application, invitationCode string, username string, email string, phone string, lang string) (bool, string) {
|
||||||
|
if isValid, msg := invitation.SimpleCheckInvitationCode(invitationCode, lang); !isValid {
|
||||||
|
return false, msg
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Username") && invitation.Username != "" && invitation.Username != username {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the username corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Email") && invitation.Email != "" && invitation.Email != email {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the email corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Phone") && invitation.Phone != "" && invitation.Phone != phone {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the phone corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
@@ -18,12 +18,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const MfaRecoveryCodesSession = "mfa_recovery_codes"
|
|
||||||
|
|
||||||
type MfaProps struct {
|
type MfaProps struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
IsPreferred bool `json:"isPreferred"`
|
IsPreferred bool `json:"isPreferred"`
|
||||||
@@ -35,9 +31,9 @@ type MfaProps struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MfaInterface interface {
|
type MfaInterface interface {
|
||||||
Initiate(ctx *context.Context, userId string) (*MfaProps, error)
|
Initiate(userId string) (*MfaProps, error)
|
||||||
SetupVerify(ctx *context.Context, passcode string) error
|
SetupVerify(passcode string) error
|
||||||
Enable(ctx *context.Context, user *User) error
|
Enable(user *User) error
|
||||||
Verify(passcode string) error
|
Verify(passcode string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,88 +16,55 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
MfaCountryCodeSession = "mfa_country_code"
|
|
||||||
MfaDestSession = "mfa_dest"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SmsMfa struct {
|
type SmsMfa struct {
|
||||||
Config *MfaProps
|
*MfaProps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, error) {
|
func (mfa *SmsMfa) Initiate(userId string) (*MfaProps, error) {
|
||||||
recoveryCode := uuid.NewString()
|
|
||||||
|
|
||||||
err := ctx.Input.CruSession.Set(MfaRecoveryCodesSession, []string{recoveryCode})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mfaProps := MfaProps{
|
mfaProps := MfaProps{
|
||||||
MfaType: mfa.Config.MfaType,
|
MfaType: mfa.MfaType,
|
||||||
RecoveryCodes: []string{recoveryCode},
|
|
||||||
}
|
}
|
||||||
return &mfaProps, nil
|
return &mfaProps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error {
|
func (mfa *SmsMfa) SetupVerify(passCode string) error {
|
||||||
destSession := ctx.Input.CruSession.Get(MfaDestSession)
|
if !util.IsEmailValid(mfa.Secret) {
|
||||||
if destSession == nil {
|
mfa.Secret, _ = util.GetE164Number(mfa.Secret, mfa.CountryCode)
|
||||||
return errors.New("dest session is missing")
|
|
||||||
}
|
|
||||||
dest := destSession.(string)
|
|
||||||
|
|
||||||
if !util.IsEmailValid(dest) {
|
|
||||||
countryCodeSession := ctx.Input.CruSession.Get(MfaCountryCodeSession)
|
|
||||||
if countryCodeSession == nil {
|
|
||||||
return errors.New("country code is missing")
|
|
||||||
}
|
|
||||||
countryCode := countryCodeSession.(string)
|
|
||||||
|
|
||||||
dest, _ = util.GetE164Number(dest, countryCode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if result := CheckVerificationCode(dest, passCode, "en"); result.Code != VerificationSuccess {
|
if result := CheckVerificationCode(mfa.Secret, passCode, "en"); result.Code != VerificationSuccess {
|
||||||
return errors.New(result.Msg)
|
return errors.New(result.Msg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
func (mfa *SmsMfa) Enable(user *User) error {
|
||||||
recoveryCodes := ctx.Input.CruSession.Get(MfaRecoveryCodesSession).([]string)
|
|
||||||
if len(recoveryCodes) == 0 {
|
|
||||||
return fmt.Errorf("recovery codes is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
columns := []string{"recovery_codes", "preferred_mfa_type"}
|
columns := []string{"recovery_codes", "preferred_mfa_type"}
|
||||||
|
|
||||||
user.RecoveryCodes = append(user.RecoveryCodes, recoveryCodes...)
|
user.RecoveryCodes = append(user.RecoveryCodes, mfa.RecoveryCodes...)
|
||||||
if user.PreferredMfaType == "" {
|
if user.PreferredMfaType == "" {
|
||||||
user.PreferredMfaType = mfa.Config.MfaType
|
user.PreferredMfaType = mfa.MfaType
|
||||||
}
|
}
|
||||||
|
|
||||||
if mfa.Config.MfaType == SmsType {
|
if mfa.MfaType == SmsType {
|
||||||
user.MfaPhoneEnabled = true
|
user.MfaPhoneEnabled = true
|
||||||
columns = append(columns, "mfa_phone_enabled")
|
columns = append(columns, "mfa_phone_enabled")
|
||||||
|
|
||||||
if user.Phone == "" {
|
if user.Phone == "" {
|
||||||
user.Phone = ctx.Input.CruSession.Get(MfaDestSession).(string)
|
user.Phone = mfa.Secret
|
||||||
user.CountryCode = ctx.Input.CruSession.Get(MfaCountryCodeSession).(string)
|
user.CountryCode = mfa.CountryCode
|
||||||
columns = append(columns, "phone", "country_code")
|
columns = append(columns, "phone", "country_code")
|
||||||
}
|
}
|
||||||
} else if mfa.Config.MfaType == EmailType {
|
} else if mfa.MfaType == EmailType {
|
||||||
user.MfaEmailEnabled = true
|
user.MfaEmailEnabled = true
|
||||||
columns = append(columns, "mfa_email_enabled")
|
columns = append(columns, "mfa_email_enabled")
|
||||||
|
|
||||||
if user.Email == "" {
|
if user.Email == "" {
|
||||||
user.Email = ctx.Input.CruSession.Get(MfaDestSession).(string)
|
user.Email = mfa.Secret
|
||||||
columns = append(columns, "email")
|
columns = append(columns, "email")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,18 +74,14 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
|
|
||||||
ctx.Input.CruSession.Delete(MfaDestSession)
|
|
||||||
ctx.Input.CruSession.Delete(MfaCountryCodeSession)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) Verify(passCode string) error {
|
func (mfa *SmsMfa) Verify(passCode string) error {
|
||||||
if !util.IsEmailValid(mfa.Config.Secret) {
|
if !util.IsEmailValid(mfa.Secret) {
|
||||||
mfa.Config.Secret, _ = util.GetE164Number(mfa.Config.Secret, mfa.Config.CountryCode)
|
mfa.Secret, _ = util.GetE164Number(mfa.Secret, mfa.CountryCode)
|
||||||
}
|
}
|
||||||
if result := CheckVerificationCode(mfa.Config.Secret, passCode, "en"); result.Code != VerificationSuccess {
|
if result := CheckVerificationCode(mfa.Secret, passCode, "en"); result.Code != VerificationSuccess {
|
||||||
return errors.New(result.Msg)
|
return errors.New(result.Msg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -131,7 +94,7 @@ func NewSmsMfaUtil(config *MfaProps) *SmsMfa {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &SmsMfa{
|
return &SmsMfa{
|
||||||
Config: config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +105,6 @@ func NewEmailMfaUtil(config *MfaProps) *SmsMfa {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &SmsMfa{
|
return &SmsMfa{
|
||||||
Config: config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,28 +16,24 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/pquerna/otp"
|
"github.com/pquerna/otp"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MfaTotpSecretSession = "mfa_totp_secret"
|
|
||||||
MfaTotpPeriodInSeconds = 30
|
MfaTotpPeriodInSeconds = 30
|
||||||
)
|
)
|
||||||
|
|
||||||
type TotpMfa struct {
|
type TotpMfa struct {
|
||||||
Config *MfaProps
|
*MfaProps
|
||||||
period uint
|
period uint
|
||||||
secretSize uint
|
secretSize uint
|
||||||
digits otp.Digits
|
digits otp.Digits
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *TotpMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, error) {
|
func (mfa *TotpMfa) Initiate(userId string) (*MfaProps, error) {
|
||||||
//issuer := beego.AppConfig.String("appname")
|
//issuer := beego.AppConfig.String("appname")
|
||||||
//if issuer == "" {
|
//if issuer == "" {
|
||||||
// issuer = "casdoor"
|
// issuer = "casdoor"
|
||||||
@@ -55,33 +51,16 @@ func (mfa *TotpMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.Input.CruSession.Set(MfaTotpSecretSession, key.Secret())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recoveryCode := uuid.NewString()
|
|
||||||
err = ctx.Input.CruSession.Set(MfaRecoveryCodesSession, []string{recoveryCode})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mfaProps := MfaProps{
|
mfaProps := MfaProps{
|
||||||
MfaType: mfa.Config.MfaType,
|
MfaType: mfa.MfaType,
|
||||||
RecoveryCodes: []string{recoveryCode},
|
Secret: key.Secret(),
|
||||||
Secret: key.Secret(),
|
URL: key.URL(),
|
||||||
URL: key.URL(),
|
|
||||||
}
|
}
|
||||||
return &mfaProps, nil
|
return &mfaProps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
func (mfa *TotpMfa) SetupVerify(passcode string) error {
|
||||||
secret := ctx.Input.CruSession.Get(MfaTotpSecretSession)
|
result, err := totp.ValidateCustom(passcode, mfa.Secret, time.Now().UTC(), totp.ValidateOpts{
|
||||||
if secret == nil {
|
|
||||||
return errors.New("totp secret is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := totp.ValidateCustom(passcode, secret.(string), time.Now().UTC(), totp.ValidateOpts{
|
|
||||||
Period: MfaTotpPeriodInSeconds,
|
Period: MfaTotpPeriodInSeconds,
|
||||||
Skew: 1,
|
Skew: 1,
|
||||||
Digits: otp.DigitsSix,
|
Digits: otp.DigitsSix,
|
||||||
@@ -98,22 +77,13 @@ func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *TotpMfa) Enable(ctx *context.Context, user *User) error {
|
func (mfa *TotpMfa) Enable(user *User) error {
|
||||||
recoveryCodes := ctx.Input.CruSession.Get(MfaRecoveryCodesSession).([]string)
|
|
||||||
if len(recoveryCodes) == 0 {
|
|
||||||
return fmt.Errorf("recovery codes is missing")
|
|
||||||
}
|
|
||||||
secret := ctx.Input.CruSession.Get(MfaTotpSecretSession).(string)
|
|
||||||
if secret == "" {
|
|
||||||
return fmt.Errorf("totp secret is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
columns := []string{"recovery_codes", "preferred_mfa_type", "totp_secret"}
|
columns := []string{"recovery_codes", "preferred_mfa_type", "totp_secret"}
|
||||||
|
|
||||||
user.RecoveryCodes = append(user.RecoveryCodes, recoveryCodes...)
|
user.RecoveryCodes = append(user.RecoveryCodes, mfa.RecoveryCodes...)
|
||||||
user.TotpSecret = secret
|
user.TotpSecret = mfa.Secret
|
||||||
if user.PreferredMfaType == "" {
|
if user.PreferredMfaType == "" {
|
||||||
user.PreferredMfaType = mfa.Config.MfaType
|
user.PreferredMfaType = mfa.MfaType
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := updateUser(user.GetId(), user, columns)
|
_, err := updateUser(user.GetId(), user, columns)
|
||||||
@@ -121,14 +91,11 @@ func (mfa *TotpMfa) Enable(ctx *context.Context, user *User) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
|
|
||||||
ctx.Input.CruSession.Delete(MfaTotpSecretSession)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *TotpMfa) Verify(passcode string) error {
|
func (mfa *TotpMfa) Verify(passcode string) error {
|
||||||
result, err := totp.ValidateCustom(passcode, mfa.Config.Secret, time.Now().UTC(), totp.ValidateOpts{
|
result, err := totp.ValidateCustom(passcode, mfa.Secret, time.Now().UTC(), totp.ValidateOpts{
|
||||||
Period: MfaTotpPeriodInSeconds,
|
Period: MfaTotpPeriodInSeconds,
|
||||||
Skew: 1,
|
Skew: 1,
|
||||||
Digits: otp.DigitsSix,
|
Digits: otp.DigitsSix,
|
||||||
@@ -153,7 +120,7 @@ func NewTotpMfaUtil(config *MfaProps) *TotpMfa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &TotpMfa{
|
return &TotpMfa{
|
||||||
Config: config,
|
MfaProps: config,
|
||||||
period: MfaTotpPeriodInSeconds,
|
period: MfaTotpPeriodInSeconds,
|
||||||
secretSize: 20,
|
secretSize: 20,
|
||||||
digits: otp.DigitsSix,
|
digits: otp.DigitsSix,
|
||||||
|
@@ -342,6 +342,11 @@ func GetDefaultApplication(id string) (*Application, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninItems(defaultApplication)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return defaultApplication, nil
|
return defaultApplication, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -312,8 +312,6 @@ func GetPaymentProvider(p *Provider) (pp.PaymentProvider, error) {
|
|||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
return nil, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) GetId() string {
|
func (p *Provider) GetId() string {
|
||||||
|
@@ -116,7 +116,7 @@ func getFilteredWebhooks(webhooks []*Webhook, action string) []*Webhook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendWebhooks(record *casvisorsdk.Record) error {
|
func SendWebhooks(record *casvisorsdk.Record) error {
|
||||||
webhooks, err := getWebhooksByOrganization(record.Organization)
|
webhooks, err := getWebhooksByOrganization("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -198,7 +198,7 @@ type Attribute struct {
|
|||||||
Values []string `xml:"AttributeValue"`
|
Values []string `xml:"AttributeValue"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, error) {
|
func GetSamlMeta(application *Application, host string, enablePostBinding bool) (*IdpEntityDescriptor, error) {
|
||||||
cert, err := getCertByApplication(application)
|
cert, err := getCertByApplication(application)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -217,6 +217,13 @@ func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, e
|
|||||||
|
|
||||||
originFrontend, originBackend := getOriginFromHost(host)
|
originFrontend, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
|
idpLocation := ""
|
||||||
|
if enablePostBinding {
|
||||||
|
idpLocation = fmt.Sprintf("%s/api/saml/redirect/%s/%s", originBackend, application.Owner, application.Name)
|
||||||
|
} else {
|
||||||
|
idpLocation = fmt.Sprintf("%s/login/saml/authorize/%s/%s", originFrontend, application.Owner, application.Name)
|
||||||
|
}
|
||||||
|
|
||||||
d := IdpEntityDescriptor{
|
d := IdpEntityDescriptor{
|
||||||
XMLName: xml.Name{
|
XMLName: xml.Name{
|
||||||
Local: "md:EntityDescriptor",
|
Local: "md:EntityDescriptor",
|
||||||
@@ -248,7 +255,7 @@ func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, e
|
|||||||
},
|
},
|
||||||
SingleSignOnService: SingleSignOnService{
|
SingleSignOnService: SingleSignOnService{
|
||||||
Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
|
Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
|
||||||
Location: fmt.Sprintf("%s/login/saml/authorize/%s/%s", originFrontend, application.Owner, application.Name),
|
Location: idpLocation,
|
||||||
},
|
},
|
||||||
ProtocolSupportEnumeration: "urn:oasis:names:tc:SAML:2.0:protocol",
|
ProtocolSupportEnumeration: "urn:oasis:names:tc:SAML:2.0:protocol",
|
||||||
},
|
},
|
||||||
@@ -442,3 +449,8 @@ func NewSamlResponse11(user *User, requestID string, host string) *etree.Element
|
|||||||
|
|
||||||
return samlResponse
|
return samlResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSamlRedirectAddress(owner string, application string, relayState string, samlRequest string, host string) string {
|
||||||
|
originF, _ := getOriginFromHost(host)
|
||||||
|
return fmt.Sprintf("%s/login/saml/authorize/%s/%s?relayState=%s&samlRequest=%s", originF, owner, application, relayState, samlRequest)
|
||||||
|
}
|
||||||
|
@@ -27,7 +27,7 @@ func getSmsClient(provider *Provider) (sender.SmsClient, error) {
|
|||||||
if provider.Type == sender.HuaweiCloud || provider.Type == sender.AzureACS {
|
if provider.Type == sender.HuaweiCloud || provider.Type == sender.AzureACS {
|
||||||
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.ProviderUrl, provider.AppId)
|
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.ProviderUrl, provider.AppId)
|
||||||
} else if provider.Type == "Custom HTTP SMS" {
|
} else if provider.Type == "Custom HTTP SMS" {
|
||||||
client, err = newHttpSmsClient(provider.Endpoint, provider.Method, provider.Title)
|
client, err = newHttpSmsClient(provider.Endpoint, provider.Method, provider.Title, provider.TemplateCode)
|
||||||
} else {
|
} else {
|
||||||
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
|
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
|
||||||
}
|
}
|
||||||
|
@@ -27,20 +27,26 @@ type HttpSmsClient struct {
|
|||||||
endpoint string
|
endpoint string
|
||||||
method string
|
method string
|
||||||
paramName string
|
paramName string
|
||||||
|
template string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHttpSmsClient(endpoint string, method string, paramName string) (*HttpSmsClient, error) {
|
func newHttpSmsClient(endpoint, method, paramName, template string) (*HttpSmsClient, error) {
|
||||||
|
if template == "" {
|
||||||
|
template = "%s"
|
||||||
|
}
|
||||||
client := &HttpSmsClient{
|
client := &HttpSmsClient{
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
method: method,
|
method: method,
|
||||||
paramName: paramName,
|
paramName: paramName,
|
||||||
|
template: template,
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
|
func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
|
||||||
phoneNumber := targetPhoneNumber[0]
|
phoneNumber := targetPhoneNumber[0]
|
||||||
content := param["code"]
|
code := param["code"]
|
||||||
|
content := fmt.Sprintf(c.template, code)
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var err error
|
var err error
|
||||||
|
@@ -793,6 +793,13 @@ func AddUser(user *User) (bool, error) {
|
|||||||
}
|
}
|
||||||
user.Ranking = int(count + 1)
|
user.Ranking = int(count + 1)
|
||||||
|
|
||||||
|
if user.Groups != nil && len(user.Groups) > 0 {
|
||||||
|
_, err = userEnforcer.UpdateGroupsForUser(user.GetId(), user.Groups)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(user)
|
affected, err := ormer.Engine.Insert(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -822,6 +829,13 @@ func AddUsers(users []*User) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.Groups != nil && len(user.Groups) > 0 {
|
||||||
|
_, err = userEnforcer.UpdateGroupsForUser(user.GetId(), user.Groups)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(users)
|
affected, err := ormer.Engine.Insert(users)
|
||||||
|
@@ -41,11 +41,7 @@ func downloadImage(client *http.Client, url string) (*bytes.Buffer, string, erro
|
|||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
fmt.Printf("downloadImage() error for url [%s]: %s\n", url, resp.Status)
|
fmt.Printf("downloadImage() error for url [%s]: %s\n", url, resp.Status)
|
||||||
if resp.StatusCode == 404 {
|
return nil, "", nil
|
||||||
return nil, "", nil
|
|
||||||
} else {
|
|
||||||
return nil, "", fmt.Errorf("failed to download gravatar image: %s", resp.Status)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the content type and determine the file extension
|
// Get the content type and determine the file extension
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
errors2 "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
|
||||||
"github.com/casbin/casbin/v2/errors"
|
"github.com/casbin/casbin/v2/errors"
|
||||||
|
|
||||||
|
"github.com/casbin/casbin/v2"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -87,7 +89,7 @@ func (e *UserGroupEnforcer) GetAllUsersByGroup(group string) ([]string, error) {
|
|||||||
|
|
||||||
users, err := e.enforcer.GetUsersForRole(GetGroupWithPrefix(group))
|
users, err := e.enforcer.GetUsersForRole(GetGroupWithPrefix(group))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errors.ErrNameNotFound {
|
if errors2.Is(err, errors.ErrNameNotFound) {
|
||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -73,10 +73,12 @@ func getObject(ctx *context.Context) (string, string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// query == "?id=built-in/admin"
|
if !(strings.HasPrefix(ctx.Request.URL.Path, "/api/get-") && strings.HasSuffix(ctx.Request.URL.Path, "s")) {
|
||||||
id := ctx.Input.Query("id")
|
// query == "?id=built-in/admin"
|
||||||
if id != "" {
|
id := ctx.Input.Query("id")
|
||||||
return util.GetOwnerAndNameFromIdNoCheck(id)
|
if id != "" {
|
||||||
|
return util.GetOwnerAndNameFromIdNoCheck(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
owner := ctx.Input.Query("owner")
|
owner := ctx.Input.Query("owner")
|
||||||
@@ -164,6 +166,10 @@ func getUrlPath(urlPath string) string {
|
|||||||
return "/api/webauthn"
|
return "/api/webauthn"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(urlPath, "/api/saml/redirect") {
|
||||||
|
return "/api/saml/redirect"
|
||||||
|
}
|
||||||
|
|
||||||
return urlPath
|
return urlPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -60,7 +60,9 @@ func initAPI() {
|
|||||||
beego.Router("/api/get-saml-login", &controllers.ApiController{}, "GET:GetSamlLogin")
|
beego.Router("/api/get-saml-login", &controllers.ApiController{}, "GET:GetSamlLogin")
|
||||||
beego.Router("/api/acs", &controllers.ApiController{}, "POST:HandleSamlLogin")
|
beego.Router("/api/acs", &controllers.ApiController{}, "POST:HandleSamlLogin")
|
||||||
beego.Router("/api/saml/metadata", &controllers.ApiController{}, "GET:GetSamlMeta")
|
beego.Router("/api/saml/metadata", &controllers.ApiController{}, "GET:GetSamlMeta")
|
||||||
beego.Router("/api/webhook", &controllers.ApiController{}, "POST:HandleOfficialAccountEvent")
|
beego.Router("/api/saml/redirect/:owner/:application", &controllers.ApiController{}, "*:HandleSamlRedirect")
|
||||||
|
beego.Router("/api/webhook", &controllers.ApiController{}, "*:HandleOfficialAccountEvent")
|
||||||
|
beego.Router("/api/get-qrcode", &controllers.ApiController{}, "GET:GetQRCode")
|
||||||
beego.Router("/api/get-webhook-event", &controllers.ApiController{}, "GET:GetWebhookEventType")
|
beego.Router("/api/get-webhook-event", &controllers.ApiController{}, "GET:GetWebhookEventType")
|
||||||
beego.Router("/api/get-captcha-status", &controllers.ApiController{}, "GET:GetCaptchaStatus")
|
beego.Router("/api/get-captcha-status", &controllers.ApiController{}, "GET:GetCaptchaStatus")
|
||||||
beego.Router("/api/callback", &controllers.ApiController{}, "POST:Callback")
|
beego.Router("/api/callback", &controllers.ApiController{}, "POST:Callback")
|
||||||
@@ -93,6 +95,7 @@ func initAPI() {
|
|||||||
|
|
||||||
beego.Router("/api/get-invitations", &controllers.ApiController{}, "GET:GetInvitations")
|
beego.Router("/api/get-invitations", &controllers.ApiController{}, "GET:GetInvitations")
|
||||||
beego.Router("/api/get-invitation", &controllers.ApiController{}, "GET:GetInvitation")
|
beego.Router("/api/get-invitation", &controllers.ApiController{}, "GET:GetInvitation")
|
||||||
|
beego.Router("/api/get-invitation-info", &controllers.ApiController{}, "GET:GetInvitationCodeInfo")
|
||||||
beego.Router("/api/update-invitation", &controllers.ApiController{}, "POST:UpdateInvitation")
|
beego.Router("/api/update-invitation", &controllers.ApiController{}, "POST:UpdateInvitation")
|
||||||
beego.Router("/api/add-invitation", &controllers.ApiController{}, "POST:AddInvitation")
|
beego.Router("/api/add-invitation", &controllers.ApiController{}, "POST:AddInvitation")
|
||||||
beego.Router("/api/delete-invitation", &controllers.ApiController{}, "POST:DeleteInvitation")
|
beego.Router("/api/delete-invitation", &controllers.ApiController{}, "POST:DeleteInvitation")
|
||||||
|
@@ -5592,6 +5592,9 @@
|
|||||||
"enableSamlCompress": {
|
"enableSamlCompress": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enableSamlPostBinding": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"enableSignUp": {
|
"enableSignUp": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@@ -16,7 +16,6 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -40,7 +39,7 @@ func GetPath(path string) string {
|
|||||||
func ListFiles(path string) []string {
|
func ListFiles(path string) []string {
|
||||||
res := []string{}
|
res := []string{}
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -14,10 +14,10 @@
|
|||||||
|
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import "io/ioutil"
|
import "os"
|
||||||
|
|
||||||
func GetUploadXlsxPath(fileId string) string {
|
func GetUploadXlsxPath(fileId string) string {
|
||||||
file, err := ioutil.TempFile("", fileId)
|
file, err := os.CreateTemp("", fileId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -119,6 +119,9 @@ func GetVersionInfo() (*VersionInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
|
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
commitOffset := 0
|
commitOffset := 0
|
||||||
version := ""
|
version := ""
|
||||||
|
@@ -70,6 +70,9 @@ func TestGetVersion(t *testing.T) {
|
|||||||
|
|
||||||
testHash := plumbing.NewHash("f8bc87eb4e5ba3256424cf14aafe0549f812f1cf")
|
testHash := plumbing.NewHash("f8bc87eb4e5ba3256424cf14aafe0549f812f1cf")
|
||||||
cIter, err := r.Log(&git.LogOptions{From: testHash})
|
cIter, err := r.Log(&git.LogOptions{From: testHash})
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
aheadCnt := 0
|
aheadCnt := 0
|
||||||
releaseVersion := ""
|
releaseVersion := ""
|
||||||
|
@@ -34,7 +34,7 @@ func init() {
|
|||||||
rePhone, _ = regexp.Compile(`(\d{3})\d*(\d{4})`)
|
rePhone, _ = regexp.Compile(`(\d{3})\d*(\d{4})`)
|
||||||
ReWhiteSpace, _ = regexp.Compile(`\s`)
|
ReWhiteSpace, _ = regexp.Compile(`\s`)
|
||||||
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
||||||
ReUserName, _ = regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
ReUserName, _ = regexp.Compile("^[a-zA-Z0-9]+([-._][a-zA-Z0-9]+)*$")
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmailValid(email string) bool {
|
func IsEmailValid(email string) bool {
|
||||||
|
@@ -735,7 +735,9 @@ class App extends Component {
|
|||||||
account={this.state.account}
|
account={this.state.account}
|
||||||
theme={this.state.themeData}
|
theme={this.state.themeData}
|
||||||
onLoginSuccess={(redirectUrl) => {
|
onLoginSuccess={(redirectUrl) => {
|
||||||
localStorage.setItem("mfaRedirectUrl", redirectUrl);
|
if (redirectUrl) {
|
||||||
|
localStorage.setItem("mfaRedirectUrl", redirectUrl);
|
||||||
|
}
|
||||||
this.getAccount();
|
this.getAccount();
|
||||||
}}
|
}}
|
||||||
onUpdateAccount={(account) => this.onUpdateAccount(account)}
|
onUpdateAccount={(account) => this.onUpdateAccount(account)}
|
||||||
|
@@ -36,6 +36,7 @@ import ThemeEditor from "./common/theme/ThemeEditor";
|
|||||||
|
|
||||||
import {Controlled as CodeMirror} from "react-codemirror2";
|
import {Controlled as CodeMirror} from "react-codemirror2";
|
||||||
import "codemirror/lib/codemirror.css";
|
import "codemirror/lib/codemirror.css";
|
||||||
|
import SigninTable from "./table/SigninTable";
|
||||||
|
|
||||||
require("codemirror/theme/material-darker.css");
|
require("codemirror/theme/material-darker.css");
|
||||||
require("codemirror/mode/htmlmixed/htmlmixed");
|
require("codemirror/mode/htmlmixed/htmlmixed");
|
||||||
@@ -116,7 +117,6 @@ class ApplicationEditPage extends React.Component {
|
|||||||
this.getApplication();
|
this.getApplication();
|
||||||
this.getOrganizations();
|
this.getOrganizations();
|
||||||
this.getProviders();
|
this.getProviders();
|
||||||
this.getSamlMetadata();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplication() {
|
getApplication() {
|
||||||
@@ -146,6 +146,8 @@ class ApplicationEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.getCerts(application.organization);
|
this.getCerts(application.organization);
|
||||||
|
|
||||||
|
this.getSamlMetadata(application.enableSamlPostBinding);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,8 +188,8 @@ class ApplicationEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getSamlMetadata() {
|
getSamlMetadata(checked) {
|
||||||
ApplicationBackend.getSamlMetadata("admin", this.state.applicationName)
|
ApplicationBackend.getSamlMetadata("admin", this.state.applicationName, checked)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
samlMetadata: data,
|
samlMetadata: data,
|
||||||
@@ -663,6 +665,17 @@ class ApplicationEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("application:Enable SAML POST binding"), i18next.t("application:Enable SAML POST binding - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={1} >
|
||||||
|
<Switch checked={this.state.application.enableSamlPostBinding} onChange={checked => {
|
||||||
|
this.updateApplicationField("enableSamlPostBinding", checked);
|
||||||
|
this.getSamlMetadata(checked);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:SAML attributes"), i18next.t("general:SAML attributes - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:SAML attributes"), i18next.t("general:SAML attributes - Tooltip"))} :
|
||||||
@@ -688,7 +701,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
||||||
copy(`${window.location.origin}/api/saml/metadata?application=admin/${encodeURIComponent(this.state.applicationName)}`);
|
copy(`${window.location.origin}/api/saml/metadata?application=admin/${encodeURIComponent(this.state.applicationName)}&post=${this.state.application.enableSamlPostBinding}`);
|
||||||
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -852,6 +865,24 @@ class ApplicationEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
{
|
||||||
|
<React.Fragment>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("application:Signin items"), i18next.t("application:Signin items - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<SigninTable
|
||||||
|
title={i18next.t("application:Signin items")}
|
||||||
|
table={this.state.application.signinItems}
|
||||||
|
onUpdateTable={(value) => {
|
||||||
|
this.updateApplicationField("signinItems", value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
{
|
{
|
||||||
!this.state.application.enableSignUp ? null : (
|
!this.state.application.enableSignUp ? null : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@@ -19,6 +19,7 @@ import * as OrganizationBackend from "./backend/OrganizationBackend";
|
|||||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import copy from "copy-to-clipboard";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@@ -99,6 +100,18 @@ class InvitationEditPage extends React.Component {
|
|||||||
{this.state.mode === "add" ? i18next.t("invitation:New Invitation") : i18next.t("invitation:Edit Invitation")}
|
{this.state.mode === "add" ? i18next.t("invitation:New Invitation") : i18next.t("invitation:Edit Invitation")}
|
||||||
<Button onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
<Button onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||||
|
<Button style={{marginLeft: "20px"}} onClick={() => {
|
||||||
|
let defaultApplication;
|
||||||
|
if (this.state.invitation.owner === "built-in") {
|
||||||
|
defaultApplication = "app-built-in";
|
||||||
|
} else {
|
||||||
|
defaultApplication = Setting.getArrayItem(this.state.organizations, "name", this.state.invitation.owner).defaultApplication;
|
||||||
|
}
|
||||||
|
copy(`${window.location.origin}/signup/${defaultApplication}?invitationCode=${this.state.invitation?.defaultCode}`);
|
||||||
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||||
|
}}>
|
||||||
|
{i18next.t("application:Copy signup page URL")}
|
||||||
|
</Button>
|
||||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||||
</div>
|
</div>
|
||||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||||
@@ -140,10 +153,24 @@ class InvitationEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.invitation.code} onChange={e => {
|
<Input value={this.state.invitation.code} onChange={e => {
|
||||||
|
const regex = /[^a-zA-Z0-9]/;
|
||||||
|
if (!regex.test(e.target.value)) {
|
||||||
|
this.updateInvitationField("defaultCode", e.target.value);
|
||||||
|
}
|
||||||
this.updateInvitationField("code", e.target.value);
|
this.updateInvitationField("code", e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("invitation:Default code"), i18next.t("invitation:Default code - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input value={this.state.invitation.defaultCode} onChange={e => {
|
||||||
|
this.updateInvitationField("defaultCode", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("invitation:Quota"), i18next.t("invitation:Quota - Tooltip"))} :
|
{Setting.getLabel(i18next.t("invitation:Quota"), i18next.t("invitation:Quota - Tooltip"))} :
|
||||||
@@ -274,6 +301,18 @@ class InvitationEditPage extends React.Component {
|
|||||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||||
<Button size="large" onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
<Button size="large" onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||||
|
<Button style={{marginLeft: "20px"}} size="large" onClick={() => {
|
||||||
|
let defaultApplication;
|
||||||
|
if (this.state.invitation.owner === "built-in") {
|
||||||
|
defaultApplication = "app-built-in";
|
||||||
|
} else {
|
||||||
|
defaultApplication = Setting.getArrayItem(this.state.organizations, "name", this.state.invitation.owner).defaultApplication;
|
||||||
|
}
|
||||||
|
copy(`${window.location.origin}/signup/${defaultApplication}?invitationCode=${this.state.invitation?.defaultCode}`);
|
||||||
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||||
|
}}>
|
||||||
|
{i18next.t("application:Copy signup page URL")}
|
||||||
|
</Button>
|
||||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -22,19 +22,20 @@ import * as InvitationBackend from "./backend/InvitationBackend";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import BaseListPage from "./BaseListPage";
|
import BaseListPage from "./BaseListPage";
|
||||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||||
import copy from "copy-to-clipboard";
|
|
||||||
|
|
||||||
class InvitationListPage extends BaseListPage {
|
class InvitationListPage extends BaseListPage {
|
||||||
newInvitation() {
|
newInvitation() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
const owner = Setting.getRequestOrganization(this.props.account);
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
|
const code = Math.random().toString(36).slice(-10);
|
||||||
return {
|
return {
|
||||||
owner: owner,
|
owner: owner,
|
||||||
name: `invitation_${randomName}`,
|
name: `invitation_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
updatedTime: moment().format(),
|
updatedTime: moment().format(),
|
||||||
displayName: `New Invitation - ${randomName}`,
|
displayName: `New Invitation - ${randomName}`,
|
||||||
code: Math.random().toString(36).slice(-10),
|
code: code,
|
||||||
|
defaultCode: code,
|
||||||
quota: 1,
|
quota: 1,
|
||||||
usedCount: 0,
|
usedCount: 0,
|
||||||
application: "All",
|
application: "All",
|
||||||
@@ -225,17 +226,11 @@ class InvitationListPage extends BaseListPage {
|
|||||||
title: i18next.t("general:Action"),
|
title: i18next.t("general:Action"),
|
||||||
dataIndex: "",
|
dataIndex: "",
|
||||||
key: "op",
|
key: "op",
|
||||||
width: "350px",
|
width: "180px",
|
||||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => {
|
|
||||||
copy(`${window.location.origin}/login/${record.owner}?invitation_code=${record.code}`);
|
|
||||||
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
|
||||||
}}>
|
|
||||||
{i18next.t("application:Copy signup page URL")}
|
|
||||||
</Button>
|
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/invitations/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/invitations/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||||
<PopconfirmModal
|
<PopconfirmModal
|
||||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Card, Checkbox, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
import {Button, Card, Checkbox, Col, Input, InputNumber, Radio, Row, Select, Switch} from "antd";
|
||||||
import {LinkOutlined} from "@ant-design/icons";
|
import {LinkOutlined} from "@ant-design/icons";
|
||||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
@@ -118,7 +118,23 @@ class ProviderEditPage extends React.Component {
|
|||||||
provider["cert"] = "";
|
provider["cert"] = "";
|
||||||
this.getCerts(value);
|
this.getCerts(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
provider[key] = value;
|
provider[key] = value;
|
||||||
|
|
||||||
|
if (provider["type"] === "WeChat") {
|
||||||
|
if (!provider["clientId"]) {
|
||||||
|
provider["signName"] = "media";
|
||||||
|
provider["disableSsl"] = true;
|
||||||
|
}
|
||||||
|
if (!provider["clientId2"]) {
|
||||||
|
provider["signName"] = "open";
|
||||||
|
provider["disableSsl"] = false;
|
||||||
|
}
|
||||||
|
if (!provider["disableSsl"]) {
|
||||||
|
provider["signName"] = "open";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
provider: provider,
|
provider: provider,
|
||||||
});
|
});
|
||||||
@@ -756,16 +772,44 @@ class ProviderEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.state.provider.type !== "WeChat" ? null : (
|
this.state.provider.type !== "WeChat" ? null : (
|
||||||
<Row style={{marginTop: "20px"}} >
|
<React.Fragment>
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Row style={{marginTop: "20px"}} >
|
||||||
{Setting.getLabel(i18next.t("provider:Enable QR code"), i18next.t("provider:Enable QR code - Tooltip"))} :
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
</Col>
|
{Setting.getLabel(i18next.t("provider:Use WeChat Media Platform in PC"), i18next.t("provider:Use WeChat Media Platform in PC - Tooltip"))} :
|
||||||
<Col span={1} >
|
</Col>
|
||||||
<Switch checked={this.state.provider.disableSsl} onChange={checked => {
|
<Col span={1} >
|
||||||
this.updateProviderField("disableSsl", checked);
|
<Switch disabled={!this.state.provider.clientId} checked={this.state.provider.disableSsl} onChange={checked => {
|
||||||
}} />
|
this.updateProviderField("disableSsl", checked);
|
||||||
</Col>
|
}} />
|
||||||
</Row>
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("token:Access token"), i18next.t("token:Access token - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input value={this.state.provider.content} disabled={!this.state.provider.disableSsl || !this.state.provider.clientId2} onChange={e => {
|
||||||
|
this.updateProviderField("content", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("provider:Follow-up action"), i18next.t("provider:Follow-up action - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Radio.Group value={this.state.provider.signName}
|
||||||
|
disabled={!this.state.provider.disableSsl || !this.state.provider.clientId || !this.state.provider.clientId2}
|
||||||
|
buttonStyle="solid"
|
||||||
|
onChange={e => {
|
||||||
|
this.updateProviderField("signName", e.target.value);
|
||||||
|
}}>
|
||||||
|
<Radio.Button value="open">{i18next.t("provider:Use WeChat Open Platform to login")}</Radio.Button>
|
||||||
|
<Radio.Button value="media">{i18next.t("provider:Use WeChat Media Platform to login")}</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -1041,7 +1085,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{["Custom HTTP SMS", "Infobip SMS"].includes(this.state.provider.type) ?
|
{["Infobip SMS"].includes(this.state.provider.type) ?
|
||||||
null :
|
null :
|
||||||
(<Row style={{marginTop: "20px"}} >
|
(<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
@@ -1253,7 +1253,11 @@ export function renderForgetLink(application, text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderLink(url, text, null);
|
const storeSigninUrl = () => {
|
||||||
|
sessionStorage.setItem("signinUrl", window.location.href);
|
||||||
|
};
|
||||||
|
|
||||||
|
return renderLink(url, text, storeSigninUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderHelmet(application) {
|
export function renderHelmet(application) {
|
||||||
|
@@ -135,8 +135,18 @@ export function loginWithSaml(values, param) {
|
|||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWechatMessageEvent() {
|
export function getWechatMessageEvent(ticket) {
|
||||||
return fetch(`${Setting.ServerUrl}/api/get-webhook-event`, {
|
return fetch(`${Setting.ServerUrl}/api/get-webhook-event?ticket=${ticket}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Accept-Language": Setting.getAcceptLanguage(),
|
||||||
|
},
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWechatQRCode(providerId) {
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/get-qrcode?id=${providerId}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
@@ -47,6 +47,7 @@ class ForgetPage extends React.Component {
|
|||||||
|
|
||||||
this.form = React.createRef();
|
this.form = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.getApplicationObj() === undefined) {
|
if (this.getApplicationObj() === undefined) {
|
||||||
if (this.state.applicationName !== undefined) {
|
if (this.state.applicationName !== undefined) {
|
||||||
@@ -153,7 +154,12 @@ class ForgetPage extends React.Component {
|
|||||||
values.userOwner = this.getApplicationObj()?.organizationObj.name;
|
values.userOwner = this.getApplicationObj()?.organizationObj.name;
|
||||||
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword, this.state.code).then(res => {
|
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword, this.state.code).then(res => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
Setting.redirectToLoginPage(this.getApplicationObj(), this.props.history);
|
const linkInStorage = sessionStorage.getItem("signinUrl");
|
||||||
|
if (linkInStorage !== null && linkInStorage !== "") {
|
||||||
|
Setting.goToLink(linkInStorage);
|
||||||
|
} else {
|
||||||
|
Setting.redirectToLoginPage(this.getApplicationObj(), this.props.history);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", res.msg);
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Checkbox, Col, Form, Input, Result, Row, Spin, Tabs} from "antd";
|
import {Button, Checkbox, Col, Form, Input, Result, Spin, Tabs} from "antd";
|
||||||
import {ArrowLeftOutlined, LockOutlined, UserOutlined} from "@ant-design/icons";
|
import {ArrowLeftOutlined, LockOutlined, UserOutlined} from "@ant-design/icons";
|
||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
|
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
|
||||||
@@ -32,11 +32,11 @@ import i18next from "i18next";
|
|||||||
import CustomGithubCorner from "../common/CustomGithubCorner";
|
import CustomGithubCorner from "../common/CustomGithubCorner";
|
||||||
import {SendCodeInput} from "../common/SendCodeInput";
|
import {SendCodeInput} from "../common/SendCodeInput";
|
||||||
import LanguageSelect from "../common/select/LanguageSelect";
|
import LanguageSelect from "../common/select/LanguageSelect";
|
||||||
import {CaptchaModal} from "../common/modal/CaptchaModal";
|
import {CaptchaModal, CaptchaRule} from "../common/modal/CaptchaModal";
|
||||||
import {CaptchaRule} from "../common/modal/CaptchaModal";
|
|
||||||
import RedirectForm from "../common/RedirectForm";
|
import RedirectForm from "../common/RedirectForm";
|
||||||
import {MfaAuthVerifyForm, NextMfa, RequiredMfa} from "./mfa/MfaAuthVerifyForm";
|
import {MfaAuthVerifyForm, NextMfa, RequiredMfa} from "./mfa/MfaAuthVerifyForm";
|
||||||
import {GoogleOneTapLoginVirtualButton} from "./GoogleLoginButton";
|
import {GoogleOneTapLoginVirtualButton} from "./GoogleLoginButton";
|
||||||
|
|
||||||
class LoginPage extends React.Component {
|
class LoginPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -494,6 +494,203 @@ class LoginPage extends React.Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderFormItem(application, signinItem) {
|
||||||
|
if (!signinItem.visible && signinItem.name !== "ForgetPassword") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signinItem.name === "Logo") {
|
||||||
|
return (
|
||||||
|
<div className="login-logo-box">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
{
|
||||||
|
Setting.renderHelmet(application)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Setting.renderLogo(application)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Back button") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
{
|
||||||
|
this.renderBackButton()
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Languages") {
|
||||||
|
return (
|
||||||
|
<div className="login-languages">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
<LanguageSelect languages={application.organizationObj.languages} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Signin methods") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
{this.renderMethodChoiceBox()}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
;
|
||||||
|
} else if (signinItem.name === "Username") {
|
||||||
|
return (
|
||||||
|
<div className="login-username">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: () => {
|
||||||
|
switch (this.state.loginMethod) {
|
||||||
|
case "verificationCodeEmail":
|
||||||
|
return i18next.t("login:Please input your Email!");
|
||||||
|
case "verificationCodePhone":
|
||||||
|
return i18next.t("login:Please input your Phone!");
|
||||||
|
case "ldap":
|
||||||
|
return i18next.t("login:Please input your LDAP username!");
|
||||||
|
default:
|
||||||
|
return i18next.t("login:Please input your Email or Phone!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (value === "") {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.loginMethod === "verificationCode") {
|
||||||
|
if (!Setting.isValidEmail(value) && !Setting.isValidPhone(value)) {
|
||||||
|
this.setState({validEmailOrPhone: false});
|
||||||
|
return Promise.reject(i18next.t("login:The input is not valid Email or phone number!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Setting.isValidEmail(value)) {
|
||||||
|
this.setState({validEmail: true});
|
||||||
|
} else {
|
||||||
|
this.setState({validEmail: false});
|
||||||
|
}
|
||||||
|
} else if (this.state.loginMethod === "verificationCodeEmail") {
|
||||||
|
if (!Setting.isValidEmail(value)) {
|
||||||
|
this.setState({validEmail: false});
|
||||||
|
this.setState({validEmailOrPhone: false});
|
||||||
|
return Promise.reject(i18next.t("login:The input is not valid Email!"));
|
||||||
|
} else {
|
||||||
|
this.setState({validEmail: true});
|
||||||
|
}
|
||||||
|
} else if (this.state.loginMethod === "verificationCodePhone") {
|
||||||
|
if (!Setting.isValidPhone(value)) {
|
||||||
|
this.setState({validEmailOrPhone: false});
|
||||||
|
return Promise.reject(i18next.t("login:The input is not valid phone number!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({validEmailOrPhone: true});
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="input"
|
||||||
|
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||||
|
placeholder={this.getPlaceholder()}
|
||||||
|
onChange={e => {
|
||||||
|
this.setState({
|
||||||
|
username: e.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Password") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
{this.renderPasswordOrCodeInput()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Forgot password?") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
<div className="login-forget-password">
|
||||||
|
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
||||||
|
<Checkbox style={{float: "left"}}>
|
||||||
|
{i18next.t("login:Auto sign in")}
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
{
|
||||||
|
signinItem.visible ? Setting.renderForgetLink(application, i18next.t("login:Forgot password?")) : null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Agreement") {
|
||||||
|
return AgreementModal.isAgreementRequired(application) ? AgreementModal.renderAgreementFormItem(application, true, {}, this) : null;
|
||||||
|
} else if (signinItem.name === "Login button") {
|
||||||
|
return (
|
||||||
|
<Form.Item className="login-button-box">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
className="login-button"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
|
||||||
|
i18next.t("login:Sign In")
|
||||||
|
}
|
||||||
|
</Button>
|
||||||
|
{
|
||||||
|
this.renderCaptchaModal(application)
|
||||||
|
}
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Providers") {
|
||||||
|
const showForm = Setting.isPasswordEnabled(application) || Setting.isCodeSigninEnabled(application) || Setting.isWebAuthnEnabled(application) || Setting.isLdapEnabled(application);
|
||||||
|
let rule ;
|
||||||
|
if (signinItem.rule === "Default") {
|
||||||
|
rule = showForm ? "Small icon" : "Big icon";
|
||||||
|
} else {
|
||||||
|
rule = signinItem.rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
<Form.Item>
|
||||||
|
{
|
||||||
|
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
|
||||||
|
return ProviderButton.renderProviderLogo(providerItem.provider, application, null, null, rule, this.props.location);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderOtherFormProvider(application)
|
||||||
|
}
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (signinItem.name.startsWith("Text ") || signinItem?.isCustom) {
|
||||||
|
return (
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
);
|
||||||
|
} else if (signinItem.name === "Signup link") {
|
||||||
|
return (
|
||||||
|
<div style={{width: "100%"}} className="login-signup-link">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
|
||||||
|
{this.renderFooter(application)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderForm(application) {
|
renderForm(application) {
|
||||||
if (this.state.msg !== null) {
|
if (this.state.msg !== null) {
|
||||||
return Util.renderMessage(this.state.msg);
|
return Util.renderMessage(this.state.msg);
|
||||||
@@ -569,116 +766,10 @@ class LoginPage extends React.Component {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{this.renderMethodChoiceBox()}
|
|
||||||
<Row style={{minHeight: 130, alignItems: "center"}}>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
|
||||||
name="username"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: () => {
|
|
||||||
switch (this.state.loginMethod) {
|
|
||||||
case "verificationCodeEmail": return i18next.t("login:Please input your Email!");
|
|
||||||
case "verificationCodePhone": return i18next.t("login:Please input your Phone!");
|
|
||||||
case "ldap": return i18next.t("login:Please input your LDAP username!");
|
|
||||||
default: return i18next.t("login:Please input your Email or Phone!");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
validator: (_, value) => {
|
|
||||||
if (value === "") {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.loginMethod === "verificationCode") {
|
{
|
||||||
if (!Setting.isValidEmail(value) && !Setting.isValidPhone(value)) {
|
application.signinItems?.map(signinItem => this.renderFormItem(application, signinItem))
|
||||||
this.setState({validEmailOrPhone: false});
|
}
|
||||||
return Promise.reject(i18next.t("login:The input is not valid Email or phone number!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Setting.isValidEmail(value)) {
|
|
||||||
this.setState({validEmail: true});
|
|
||||||
} else {
|
|
||||||
this.setState({validEmail: false});
|
|
||||||
}
|
|
||||||
} else if (this.state.loginMethod === "verificationCodeEmail") {
|
|
||||||
if (!Setting.isValidEmail(value)) {
|
|
||||||
this.setState({validEmail: false});
|
|
||||||
this.setState({validEmailOrPhone: false});
|
|
||||||
return Promise.reject(i18next.t("login:The input is not valid Email!"));
|
|
||||||
} else {
|
|
||||||
this.setState({validEmail: true});
|
|
||||||
}
|
|
||||||
} else if (this.state.loginMethod === "verificationCodePhone") {
|
|
||||||
if (!Setting.isValidPhone(value)) {
|
|
||||||
this.setState({validEmailOrPhone: false});
|
|
||||||
return Promise.reject(i18next.t("login:The input is not valid phone number!"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({validEmailOrPhone: true});
|
|
||||||
return Promise.resolve();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
id="input"
|
|
||||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
|
||||||
placeholder={this.getPlaceholder()}
|
|
||||||
onChange={e => {
|
|
||||||
this.setState({
|
|
||||||
username: e.target.value,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
{
|
|
||||||
this.renderPasswordOrCodeInput()
|
|
||||||
}
|
|
||||||
</Row>
|
|
||||||
<div style={{display: "inline-flex", justifyContent: "space-between", width: "320px", marginBottom: AgreementModal.isAgreementRequired(application) ? "5px" : "25px"}}>
|
|
||||||
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
|
||||||
<Checkbox style={{float: "left"}}>
|
|
||||||
{i18next.t("login:Auto sign in")}
|
|
||||||
</Checkbox>
|
|
||||||
</Form.Item>
|
|
||||||
{
|
|
||||||
Setting.renderForgetLink(application, i18next.t("login:Forgot password?"))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{AgreementModal.isAgreementRequired(application) ? AgreementModal.renderAgreementFormItem(application, true, {}, this) : null}
|
|
||||||
<Form.Item>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
htmlType="submit"
|
|
||||||
style={{width: "100%", marginBottom: "5px"}}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
|
|
||||||
i18next.t("login:Sign In")
|
|
||||||
}
|
|
||||||
</Button>
|
|
||||||
{
|
|
||||||
this.renderCaptchaModal(application)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.renderFooter(application)
|
|
||||||
}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item>
|
|
||||||
{
|
|
||||||
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
|
|
||||||
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small", this.props.location);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.renderOtherFormProvider(application)
|
|
||||||
}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -694,20 +785,7 @@ class LoginPage extends React.Component {
|
|||||||
:
|
:
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
{
|
{application.signinItems.map(signinItem => signinItem.name === "Providers" || signinItem.name === "Signup link" ? this.renderFormItem(application, signinItem) : null)}
|
||||||
application.providers?.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
|
|
||||||
return ProviderButton.renderProviderLogo(providerItem.provider, application, 40, 10, "big", this.props.location);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.renderOtherFormProvider(application)
|
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<br />
|
|
||||||
{
|
|
||||||
this.renderFooter(application)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -760,7 +838,7 @@ class LoginPage extends React.Component {
|
|||||||
|
|
||||||
renderFooter(application) {
|
renderFooter(application) {
|
||||||
return (
|
return (
|
||||||
<span style={{float: "right"}}>
|
<div>
|
||||||
{
|
{
|
||||||
!application.enableSignUp ? null : (
|
!application.enableSignUp ? null : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@@ -771,7 +849,7 @@ class LoginPage extends React.Component {
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</span>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,33 +967,37 @@ class LoginPage extends React.Component {
|
|||||||
if (this.state.loginMethod === "password" || this.state.loginMethod === "ldap") {
|
if (this.state.loginMethod === "password" || this.state.loginMethod === "ldap") {
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Item
|
<div className="login-password">
|
||||||
name="password"
|
<Form.Item
|
||||||
rules={[{required: true, message: i18next.t("login:Please input your password!")}]}
|
name="password"
|
||||||
>
|
rules={[{required: true, message: i18next.t("login:Please input your password!")}]}
|
||||||
<Input.Password
|
>
|
||||||
prefix={<LockOutlined className="site-form-item-icon" />}
|
<Input.Password
|
||||||
type="password"
|
prefix={<LockOutlined className="site-form-item-icon" />}
|
||||||
placeholder={i18next.t("general:Password")}
|
type="password"
|
||||||
disabled={this.state.loginMethod === "password" ? !Setting.isPasswordEnabled(application) : !Setting.isLdapEnabled(application)}
|
placeholder={i18next.t("general:Password")}
|
||||||
/>
|
disabled={this.state.loginMethod === "password" ? !Setting.isPasswordEnabled(application) : !Setting.isLdapEnabled(application)}
|
||||||
</Form.Item>
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
} else if (this.state.loginMethod?.includes("verificationCode")) {
|
} else if (this.state.loginMethod?.includes("verificationCode")) {
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Item
|
<div className="login-password">
|
||||||
name="code"
|
<Form.Item
|
||||||
rules={[{required: true, message: i18next.t("login:Please input your code!")}]}
|
name="code"
|
||||||
>
|
rules={[{required: true, message: i18next.t("login:Please input your code!")}]}
|
||||||
<SendCodeInput
|
>
|
||||||
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
<SendCodeInput
|
||||||
method={"login"}
|
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
||||||
onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]}
|
method={"login"}
|
||||||
application={application}
|
onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]}
|
||||||
/>
|
application={application}
|
||||||
</Form.Item>
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -952,7 +1034,7 @@ class LoginPage extends React.Component {
|
|||||||
if (items.length > 1) {
|
if (items.length > 1) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Tabs items={items} size={"small"} defaultActiveKey={this.getDefaultLoginMethod(application)} onChange={(key) => {
|
<Tabs className="signin-methods" items={items} size={"small"} defaultActiveKey={this.getDefaultLoginMethod(application)} onChange={(key) => {
|
||||||
this.setState({loginMethod: key});
|
this.setState({loginMethod: key});
|
||||||
}} centered>
|
}} centered>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@@ -1047,10 +1129,10 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBackButton() {
|
renderBackButton() {
|
||||||
if (this.state.orgChoiceMode === "None") {
|
if (this.state.orgChoiceMode === "None" || this.props.preview === "auto") {
|
||||||
return (
|
return (
|
||||||
<Button type="text" size="large" icon={<ArrowLeftOutlined />}
|
<Button type="text" size="large" icon={<ArrowLeftOutlined />}
|
||||||
style={{top: "65px", left: "15px", position: "absolute"}}
|
className="back-button"
|
||||||
onClick={() => history.back()}>
|
onClick={() => history.back()}>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@@ -1099,16 +1181,6 @@ class LoginPage extends React.Component {
|
|||||||
<div className="login-form">
|
<div className="login-form">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
{
|
|
||||||
Setting.renderHelmet(application)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Setting.renderLogo(application)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.renderBackButton()
|
|
||||||
}
|
|
||||||
<LanguageSelect languages={application.organizationObj.languages} style={{top: "55px", right: "5px", position: "absolute"}} />
|
|
||||||
{
|
{
|
||||||
this.renderLoginPanel(application)
|
this.renderLoginPanel(application)
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Col, Result, Row, Steps} from "antd";
|
import {Button, Col, Result, Row, Spin, Steps} from "antd";
|
||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
@@ -42,13 +42,20 @@ class MfaSetupPage extends React.Component {
|
|||||||
mfaProps: null,
|
mfaProps: null,
|
||||||
mfaType: params.get("mfaType") ?? SmsMfaType,
|
mfaType: params.get("mfaType") ?? SmsMfaType,
|
||||||
isPromptPage: props.isPromptPage || location.state?.from !== undefined,
|
isPromptPage: props.isPromptPage || location.state?.from !== undefined,
|
||||||
|
loading: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getApplication();
|
this.getApplication();
|
||||||
if (this.state.current === 1) {
|
if (this.state.current === 1) {
|
||||||
this.initMfaProps();
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.initMfaProps();
|
||||||
|
}, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +92,7 @@ class MfaSetupPage extends React.Component {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.setState({
|
this.setState({
|
||||||
mfaProps: res.data,
|
mfaProps: res.data,
|
||||||
|
loading: false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
||||||
@@ -231,15 +239,17 @@ class MfaSetupPage extends React.Component {
|
|||||||
<p style={{textAlign: "center", fontSize: "16px", marginTop: "10px"}}>{i18next.t("mfa:Each time you sign in to your Account, you'll need your password and a authentication code")}</p>
|
<p style={{textAlign: "center", fontSize: "16px", marginTop: "10px"}}>{i18next.t("mfa:Each time you sign in to your Account, you'll need your password and a authentication code")}</p>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Steps current={this.state.current}
|
<Spin spinning={this.state.loading}>
|
||||||
items={[
|
<Steps current={this.state.current}
|
||||||
{title: i18next.t("mfa:Verify Password"), icon: <UserOutlined />},
|
items={[
|
||||||
{title: i18next.t("mfa:Verify Code"), icon: <KeyOutlined />},
|
{title: i18next.t("mfa:Verify Password"), icon: <UserOutlined />},
|
||||||
{title: i18next.t("general:Enable"), icon: <CheckOutlined />},
|
{title: i18next.t("mfa:Verify Code"), icon: <KeyOutlined />},
|
||||||
]}
|
{title: i18next.t("general:Enable"), icon: <CheckOutlined />},
|
||||||
style={{width: "90%", maxWidth: "500px", margin: "auto", marginTop: "50px",
|
]}
|
||||||
}} >
|
style={{width: "90%", maxWidth: "500px", margin: "auto", marginTop: "50px",
|
||||||
</Steps>
|
}} >
|
||||||
|
</Steps>
|
||||||
|
</Spin>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
||||||
<div style={{marginTop: "10px", textAlign: "center"}}>
|
<div style={{marginTop: "10px", textAlign: "center"}}>
|
||||||
|
@@ -377,7 +377,7 @@ export function getProviderLogoWidget(provider) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAuthUrl(application, provider, method) {
|
export function getAuthUrl(application, provider, method, code) {
|
||||||
if (application === null || provider === null) {
|
if (application === null || provider === null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -418,6 +418,9 @@ export function getAuthUrl(application, provider, method) {
|
|||||||
if (navigator.userAgent.includes("MicroMessenger")) {
|
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`;
|
return `${authInfo[provider.type].mpEndpoint}?appid=${provider.clientId2}&redirect_uri=${redirectUri}&state=${state}&scope=${authInfo[provider.type].mpScope}&response_type=code#wechat_redirect`;
|
||||||
} else {
|
} else {
|
||||||
|
if (provider.clientId2 && provider?.disableSsl && provider?.signName === "media") {
|
||||||
|
return `${window.location.origin}/callback?state=${state}&code=${"wechat_oa:" + code}`;
|
||||||
|
}
|
||||||
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}#wechat_redirect`;
|
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}#wechat_redirect`;
|
||||||
}
|
}
|
||||||
} else if (provider.type === "WeCom") {
|
} else if (provider.type === "WeCom") {
|
||||||
|
@@ -43,6 +43,7 @@ import OktaLoginButton from "./OktaLoginButton";
|
|||||||
import DouyinLoginButton from "./DouyinLoginButton";
|
import DouyinLoginButton from "./DouyinLoginButton";
|
||||||
import LoginButton from "./LoginButton";
|
import LoginButton from "./LoginButton";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
|
import * as Setting from "../Setting";
|
||||||
import {getEvent} from "./Util";
|
import {getEvent} from "./Util";
|
||||||
import {Modal} from "antd";
|
import {Modal} from "antd";
|
||||||
|
|
||||||
@@ -130,45 +131,54 @@ export function goToWeb3Url(application, provider, method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renderProviderLogo(provider, application, width, margin, size, location) {
|
export function renderProviderLogo(provider, application, width, margin, size, location) {
|
||||||
if (size === "small") {
|
if (size === "Small icon") {
|
||||||
if (provider.category === "OAuth") {
|
if (provider.category === "OAuth") {
|
||||||
if (provider.type === "WeChat" && provider.clientId2 !== "" && provider.clientSecret2 !== "" && provider.content !== "" && provider.disableSsl === true && !navigator.userAgent.includes("MicroMessenger")) {
|
if (provider.type === "WeChat" && provider.clientId2 !== "" && provider.clientSecret2 !== "" && provider.disableSsl === true && !navigator.userAgent.includes("MicroMessenger")) {
|
||||||
const info = async() => {
|
const info = async() => {
|
||||||
const t1 = setInterval(await getEvent, 1000, application, provider);
|
AuthBackend.getWechatQRCode(`${provider.owner}/${provider.name}`).then(
|
||||||
{Modal.info({
|
async res => {
|
||||||
title: i18next.t("provider:Please use WeChat and scan the QR code to sign in"),
|
if (res.status !== "ok") {
|
||||||
content: (
|
Setting.showMessage("error", res?.msg);
|
||||||
<div>
|
return;
|
||||||
<img width={256} height={256} src = {"data:image/png;base64," + provider.content} alt="Wechat QR code" style={{margin: margin}} />
|
}
|
||||||
</div>
|
|
||||||
),
|
const t1 = setInterval(await getEvent, 1000, application, provider, res.data2);
|
||||||
onOk() {
|
{Modal.info({
|
||||||
window.clearInterval(t1);
|
title: i18next.t("provider:Please use WeChat to scan the QR code and follow the official account for sign in"),
|
||||||
},
|
content: (
|
||||||
});}
|
<div style={{marginRight: "34px"}}>
|
||||||
|
<img src = {"data:image/png;base64," + res.data} alt="Wechat QR code" style={{width: "100%"}} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
onOk() {
|
||||||
|
window.clearInterval(t1);
|
||||||
|
},
|
||||||
|
});}
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<a key={provider.displayName} >
|
<a key={provider.displayName} >
|
||||||
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} style={{margin: margin}} onClick={info} />
|
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={{margin: margin}} onClick={info} />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "signup")}>
|
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "signup")}>
|
||||||
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} style={{margin: margin}} />
|
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={{margin: margin}} />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (provider.category === "SAML") {
|
} else if (provider.category === "SAML") {
|
||||||
return (
|
return (
|
||||||
<a key={provider.displayName} onClick={() => goToSamlUrl(provider, location)}>
|
<a key={provider.displayName} onClick={() => goToSamlUrl(provider, location)}>
|
||||||
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} style={{margin: margin}} />
|
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={{margin: margin}} />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (provider.category === "Web3") {
|
} else if (provider.category === "Web3") {
|
||||||
return (
|
return (
|
||||||
<a key={provider.displayName} onClick={() => goToWeb3Url(application, provider, "signup")}>
|
<a key={provider.displayName} onClick={() => goToWeb3Url(application, provider, "signup")}>
|
||||||
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} style={{margin: margin}} />
|
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={{margin: margin}} />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -183,7 +193,7 @@ export function renderProviderLogo(provider, application, width, margin, size, l
|
|||||||
return (
|
return (
|
||||||
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "signup")} style={customAStyle}>
|
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "signup")} style={customAStyle}>
|
||||||
<button style={customButtonStyle}>
|
<button style={customButtonStyle}>
|
||||||
<img width={26} src={getProviderLogoURL(provider)} alt={provider.displayName} style={customImgStyle} />
|
<img width={26} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={customImgStyle} />
|
||||||
<span style={customSpanStyle}>{text}</span>
|
<span style={customSpanStyle}>{text}</span>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
@@ -192,7 +202,7 @@ export function renderProviderLogo(provider, application, width, margin, size, l
|
|||||||
return (
|
return (
|
||||||
<a key={provider.displayName} onClick={() => goToSamlUrl(provider, location)} style={customAStyle}>
|
<a key={provider.displayName} onClick={() => goToSamlUrl(provider, location)} style={customAStyle}>
|
||||||
<button style={customButtonStyle}>
|
<button style={customButtonStyle}>
|
||||||
<img width={26} src={getProviderLogoURL(provider)} alt={provider.displayName} style={customImgStyle} />
|
<img width={26} src={getProviderLogoURL(provider)} alt={provider.displayName} className="provider-img" style={customImgStyle} />
|
||||||
<span style={customSpanStyle}>{text}</span>
|
<span style={customSpanStyle}>{text}</span>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
@@ -202,7 +212,7 @@ export function renderProviderLogo(provider, application, width, margin, size, l
|
|||||||
// big button, for disable password signin
|
// big button, for disable password signin
|
||||||
if (provider.category === "SAML") {
|
if (provider.category === "SAML") {
|
||||||
return (
|
return (
|
||||||
<div key={provider.displayName} style={{marginBottom: "10px"}}>
|
<div key={provider.displayName} className="provider-big-img">
|
||||||
<a onClick={() => goToSamlUrl(provider, location)}>
|
<a onClick={() => goToSamlUrl(provider, location)}>
|
||||||
{
|
{
|
||||||
getSigninButton(provider)
|
getSigninButton(provider)
|
||||||
@@ -212,7 +222,7 @@ export function renderProviderLogo(provider, application, width, margin, size, l
|
|||||||
);
|
);
|
||||||
} else if (provider.category === "Web3") {
|
} else if (provider.category === "Web3") {
|
||||||
return (
|
return (
|
||||||
<div key={provider.displayName} style={{marginBottom: "10px"}}>
|
<div key={provider.displayName} className="provider-big-img">
|
||||||
<a onClick={() => goToWeb3Url(application, provider, "signup")}>
|
<a onClick={() => goToWeb3Url(application, provider, "signup")}>
|
||||||
{
|
{
|
||||||
getSigninButton(provider)
|
getSigninButton(provider)
|
||||||
@@ -222,7 +232,7 @@ export function renderProviderLogo(provider, application, width, margin, size, l
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div key={provider.displayName} style={{marginBottom: "10px"}}>
|
<div key={provider.displayName} className="provider-big-img">
|
||||||
<a href={Provider.getAuthUrl(application, provider, "signup")}>
|
<a href={Provider.getAuthUrl(application, provider, "signup")}>
|
||||||
{
|
{
|
||||||
getSigninButton(provider)
|
getSigninButton(provider)
|
||||||
|
@@ -29,6 +29,7 @@ import LanguageSelect from "../common/select/LanguageSelect";
|
|||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||||
import * as PasswordChecker from "../common/PasswordChecker";
|
import * as PasswordChecker from "../common/PasswordChecker";
|
||||||
|
import * as InvitationBackend from "../backend/InvitationBackend";
|
||||||
|
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
@@ -93,6 +94,15 @@ class SignupPage extends React.Component {
|
|||||||
if (this.getApplicationObj() === undefined) {
|
if (this.getApplicationObj() === undefined) {
|
||||||
if (this.state.applicationName !== null) {
|
if (this.state.applicationName !== null) {
|
||||||
this.getApplication(this.state.applicationName);
|
this.getApplication(this.state.applicationName);
|
||||||
|
|
||||||
|
const sp = new URLSearchParams(window.location.search);
|
||||||
|
if (sp.has("invitationCode")) {
|
||||||
|
const invitationCode = sp.get("invitationCode");
|
||||||
|
this.setState({invitationCode: invitationCode});
|
||||||
|
if (invitationCode !== "") {
|
||||||
|
this.getInvitationCodeInfo(invitationCode, "admin/" + this.state.applicationName);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (oAuthParams !== null) {
|
} else if (oAuthParams !== null) {
|
||||||
this.getApplicationLogin(oAuthParams);
|
this.getApplicationLogin(oAuthParams);
|
||||||
} else {
|
} else {
|
||||||
@@ -133,6 +143,17 @@ class SignupPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInvitationCodeInfo(invitationCode, application) {
|
||||||
|
InvitationBackend.getInvitationCodeInfo(invitationCode, application)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({invitation: res.data});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getResultPath(application, signupParams) {
|
getResultPath(application, signupParams) {
|
||||||
if (signupParams?.plan && signupParams?.pricing) {
|
if (signupParams?.plan && signupParams?.pricing) {
|
||||||
// the prompt page needs the user to be signed in, so for paid-user sign up, just go to buy-plan page
|
// the prompt page needs the user to be signed in, so for paid-user sign up, just go to buy-plan page
|
||||||
@@ -235,7 +256,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation.username !== ""} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
} else if (signupItem.name === "Display name") {
|
} else if (signupItem.name === "Display name") {
|
||||||
@@ -363,7 +384,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} onChange={e => this.setState({email: e.target.value})} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation.email !== ""} onChange={e => this.setState({email: e.target.value})} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
signupItem.rule !== "No verification" &&
|
signupItem.rule !== "No verification" &&
|
||||||
@@ -434,6 +455,7 @@ class SignupPage extends React.Component {
|
|||||||
<Input
|
<Input
|
||||||
placeholder={signupItem.placeholder}
|
placeholder={signupItem.placeholder}
|
||||||
style={{width: "65%"}}
|
style={{width: "65%"}}
|
||||||
|
disabled={this.state.invitation !== undefined && this.state.invitation.phone !== ""}
|
||||||
onChange={e => this.setState({phone: e.target.value})}
|
onChange={e => this.setState({phone: e.target.value})}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -524,7 +546,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation !== ""} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
} else if (signupItem.name === "Agreement") {
|
} else if (signupItem.name === "Agreement") {
|
||||||
@@ -554,6 +576,20 @@ class SignupPage extends React.Component {
|
|||||||
</Result>
|
</Result>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (this.state.invitation !== undefined) {
|
||||||
|
if (this.state.invitation.username !== "") {
|
||||||
|
this.form.current?.setFieldValue("username", this.state.invitation.username);
|
||||||
|
}
|
||||||
|
if (this.state.invitation.email !== "") {
|
||||||
|
this.form.current?.setFieldValue("email", this.state.invitation.email);
|
||||||
|
}
|
||||||
|
if (this.state.invitation.phone !== "") {
|
||||||
|
this.form.current?.setFieldValue("phone", this.state.invitation.phone);
|
||||||
|
}
|
||||||
|
if (this.state.invitationCode !== "") {
|
||||||
|
this.form.current?.setFieldValue("invitationCode", this.state.invitationCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
{...formItemLayout}
|
{...formItemLayout}
|
||||||
@@ -613,7 +649,7 @@ class SignupPage extends React.Component {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
|
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
|
||||||
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small", this.props.location);
|
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "Small icon", this.props.location);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</Form>
|
</Form>
|
||||||
|
@@ -188,11 +188,12 @@ export function getQueryParamsFromState(state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEvent(application, provider) {
|
export function getEvent(application, provider, ticket) {
|
||||||
getWechatMessageEvent()
|
getWechatMessageEvent(ticket)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.data === "SCAN" || res.data === "subscribe") {
|
if (res.data === "SCAN" || res.data === "subscribe") {
|
||||||
Setting.goToLink(Provider.getAuthUrl(application, provider, "signup"));
|
const code = res?.data2;
|
||||||
|
Setting.goToLink(Provider.getAuthUrl(application, provider, "signup", code));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -89,8 +89,8 @@ export function deleteApplication(application) {
|
|||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSamlMetadata(owner, name) {
|
export function getSamlMetadata(owner, name, enablePostBinding) {
|
||||||
return fetch(`${Setting.ServerUrl}/api/saml/metadata?application=${owner}/${encodeURIComponent(name)}`, {
|
return fetch(`${Setting.ServerUrl}/api/saml/metadata?application=${owner}/${encodeURIComponent(name)}&enablePostBinding=${enablePostBinding}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
@@ -34,6 +34,16 @@ export function getInvitation(owner, name) {
|
|||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getInvitationCodeInfo(code, applicationName) {
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/get-invitation-info?code=${code}&applicationId=${encodeURIComponent(applicationName)}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Accept-Language": Setting.getAcceptLanguage(),
|
||||||
|
},
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
export function updateInvitation(owner, name, invitation) {
|
export function updateInvitation(owner, name, invitation) {
|
||||||
const newInvitation = Setting.deepCopy(invitation);
|
const newInvitation = Setting.deepCopy(invitation);
|
||||||
return fetch(`${Setting.ServerUrl}/api/update-invitation?id=${owner}/${encodeURIComponent(name)}`, {
|
return fetch(`${Setting.ServerUrl}/api/update-invitation?id=${owner}/${encodeURIComponent(name)}`, {
|
||||||
|
@@ -81,6 +81,7 @@ export function renderAgreementFormItem(application, required, layout, ths) {
|
|||||||
name="agreement"
|
name="agreement"
|
||||||
key="agreement"
|
key="agreement"
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
|
className="login-agreement"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: required,
|
required: required,
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "Wenn eine angemeldete Session in Casdoor vorhanden ist, wird diese automatisch für die Anmeldung auf Anwendungsebene verwendet",
|
"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": "Background-URL",
|
||||||
"Background URL - Tooltip": "URL des Hintergrundbildes, das auf der Anmeldeseite angezeigt wird",
|
"Background URL - Tooltip": "URL des Hintergrundbildes, das auf der Anmeldeseite angezeigt wird",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Zentrum",
|
"Center": "Zentrum",
|
||||||
"Copy SAML metadata URL": "SAML-Metadaten-URL kopieren",
|
"Copy SAML metadata URL": "SAML-Metadaten-URL kopieren",
|
||||||
"Copy prompt page URL": "URL der Prompt-Seite kopieren",
|
"Copy prompt page URL": "URL der Prompt-Seite kopieren",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "Bei der Verwendung von Drittanbietern zur Anmeldung wird, wenn es in der Organisation einen Benutzer mit der gleichen E-Mail gibt, automatisch die Drittanbieter-Anmelde-Methode mit diesem Benutzer verbunden",
|
"Enable Email linking - Tooltip": "Bei der Verwendung von Drittanbietern zur Anmeldung wird, wenn es in der Organisation einen Benutzer mit der gleichen E-Mail gibt, automatisch die Drittanbieter-Anmelde-Methode mit diesem Benutzer verbunden",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Aktivieren Sie SAML-Komprimierung",
|
"Enable SAML compression": "Aktivieren Sie SAML-Komprimierung",
|
||||||
"Enable SAML compression - Tooltip": "Ob SAML-Antwortnachrichten komprimiert werden sollen, wenn Casdoor als SAML-IdP verwendet wird",
|
"Enable SAML compression - Tooltip": "Ob SAML-Antwortnachrichten komprimiert werden sollen, wenn Casdoor als SAML-IdP verwendet wird",
|
||||||
"Enable side panel": "Sidepanel aktivieren",
|
"Enable side panel": "Sidepanel aktivieren",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Registrierungsfehler",
|
"Sign Up Error": "Registrierungsfehler",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Anmeldesession",
|
"Signin session": "Anmeldesession",
|
||||||
"Signup items": "Registrierungs Items",
|
"Signup items": "Registrierungs Items",
|
||||||
"Signup items - Tooltip": "Items, die Benutzer ausfüllen müssen, wenn sie neue Konten registrieren",
|
"Signup items - Tooltip": "Items, die Benutzer ausfüllen müssen, wenn sie neue Konten registrieren",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "Die Anwendung erlaubt es nicht, ein neues Konto zu registrieren",
|
"The application does not allow to sign up new account": "Die Anwendung erlaubt es nicht, ein neues Konto zu registrieren",
|
||||||
"Token expire": "Token läuft ab",
|
"Token expire": "Token läuft ab",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Tabellenname des Policy Stores",
|
"Adapter - Tooltip": "Tabellenname des Policy Stores",
|
||||||
"Adapters": "Adapter",
|
"Adapters": "Adapter",
|
||||||
"Add": "Hinzufügen",
|
"Add": "Hinzufügen",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Zugehörigkeits-URL",
|
"Affiliation URL": "Zugehörigkeits-URL",
|
||||||
"Affiliation URL - Tooltip": "Die Homepage-URL für die Zugehörigkeit",
|
"Affiliation URL - Tooltip": "Die Homepage-URL für die Zugehörigkeit",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Benutzerdefinierte URL für die Registrierungsseite. Wenn nicht festgelegt, wird die standardmäßige Casdoor-Registrierungsseite verwendet. Wenn sie festgelegt wird, werden die Registrierungslinks auf verschiedenen Casdoor-Seiten auf diese URL umgeleitet",
|
"Signup URL - Tooltip": "Benutzerdefinierte URL für die Registrierungsseite. Wenn nicht festgelegt, wird die standardmäßige Casdoor-Registrierungsseite verwendet. Wenn sie festgelegt wird, werden die Registrierungslinks auf verschiedenen Casdoor-Seiten auf diese URL umgeleitet",
|
||||||
"Signup application": "Anmeldeanwendung",
|
"Signup application": "Anmeldeanwendung",
|
||||||
"Signup application - Tooltip": "Durch welche Anwendung hat sich der Benutzer angemeldet, als er sich registriert hat?",
|
"Signup application - Tooltip": "Durch welche Anwendung hat sich der Benutzer angemeldet, als er sich registriert hat?",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Entschuldigung, die von Ihnen besuchte Seite existiert nicht.",
|
"Sorry, the page you visited does not exist.": "Entschuldigung, die von Ihnen besuchte Seite existiert nicht.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Entschuldigung, der von Ihnen besuchte Benutzer existiert nicht oder Sie sind nicht autorisiert, auf diesen Benutzer zuzugreifen.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Entschuldigung, der von Ihnen besuchte Benutzer existiert nicht oder Sie sind nicht autorisiert, auf diesen Benutzer zuzugreifen.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Es tut uns leid, aber Sie haben keine Berechtigung, auf diese Seite zuzugreifen, oder Sie sind nicht angemeldet.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Es tut uns leid, aber Sie haben keine Berechtigung, auf diese Seite zuzugreifen, oder Sie sind nicht angemeldet.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Automatische Anmeldung",
|
"Auto sign in": "Automatische Anmeldung",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Weitermachen mit",
|
"Continue with": "Weitermachen mit",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "E-Mail oder Telefon",
|
"Email or phone": "E-Mail oder Telefon",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Laden",
|
"Loading": "Laden",
|
||||||
"Logging out...": "Ausloggen...",
|
"Logging out...": "Ausloggen...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "Kein Konto?",
|
"No account?": "Kein Konto?",
|
||||||
"Or sign in with another account": "Oder mit einem anderen Konto anmelden",
|
"Or sign in with another account": "Oder mit einem anderen Konto anmelden",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Inhalt der E-Mail",
|
"Email content - Tooltip": "Inhalt der E-Mail",
|
||||||
"Email title": "Email-Titel",
|
"Email title": "Email-Titel",
|
||||||
"Email title - Tooltip": "Betreff der E-Mail",
|
"Email title - Tooltip": "Betreff der E-Mail",
|
||||||
"Enable QR code": "QR-Code aktivieren",
|
|
||||||
"Enable QR code - Tooltip": "Ob das Scannen von QR-Codes zum Einloggen aktiviert werden soll",
|
|
||||||
"Endpoint": "Endpunkt",
|
"Endpoint": "Endpunkt",
|
||||||
"Endpoint (Intranet)": "Endpunkt (Intranet)",
|
"Endpoint (Intranet)": "Endpunkt (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "From address - Tooltip",
|
"From address - Tooltip": "From address - Tooltip",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Metadaten erfolgreich analysiert",
|
"Parse metadata successfully": "Metadaten erfolgreich analysiert",
|
||||||
"Path prefix": "Pfadpräfix",
|
"Path prefix": "Pfadpräfix",
|
||||||
"Path prefix - Tooltip": "Bucket-Pfad-Präfix für Objektspeicher",
|
"Path prefix - Tooltip": "Bucket-Pfad-Präfix für Objektspeicher",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Bitte verwenden Sie WeChat und scanne den QR-Code ein, um dich anzumelden",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Hafen",
|
"Port": "Hafen",
|
||||||
"Port - Tooltip": "Stellen Sie sicher, dass der Port offen ist",
|
"Port - Tooltip": "Stellen Sie sicher, dass der Port offen ist",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token-URL",
|
"Token URL - Tooltip": "Token-URL",
|
||||||
"Type": "Typ",
|
"Type": "Typ",
|
||||||
"Type - Tooltip": "Wählen Sie einen Typ aus",
|
"Type - Tooltip": "Wählen Sie einen Typ aus",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Use C14N10 instead of C14N11 in SAML",
|
"Enable SAML C14N10 - Tooltip": "Use C14N10 instead of C14N11 in SAML",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Items for users to fill in when signing up",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Can be a single string as an invitation code, or a regular expression. All strings matching the regular expression are valid invitation codes",
|
"Code - Tooltip": "Can be a single string as an invitation code, or a regular expression. All strings matching the regular expression are valid invitation codes",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow",
|
"User flow - Tooltip": "User flow",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"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",
|
"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": "URL de fondo",
|
||||||
"Background URL - Tooltip": "URL de la imagen de fondo utilizada en la página de inicio de sesión",
|
"Background URL - Tooltip": "URL de la imagen de fondo utilizada en la página de inicio de sesión",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Centro",
|
"Center": "Centro",
|
||||||
"Copy SAML metadata URL": "Copia la URL de metadatos SAML",
|
"Copy SAML metadata URL": "Copia la URL de metadatos SAML",
|
||||||
"Copy prompt page URL": "Copiar URL de la página del prompt",
|
"Copy prompt page URL": "Copiar URL de la página del prompt",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "Cuando se utilizan proveedores externos de inicio de sesión, si hay un usuario en la organización con el mismo correo electrónico, el método de inicio de sesión externo se asociará automáticamente con ese usuario",
|
"Enable Email linking - Tooltip": "Cuando se utilizan proveedores externos de inicio de sesión, si hay un usuario en la organización con el mismo correo electrónico, el método de inicio de sesión externo se asociará automáticamente con ese usuario",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Activar la compresión SAML",
|
"Enable SAML compression": "Activar la compresión SAML",
|
||||||
"Enable SAML compression - Tooltip": "Si comprimir o no los mensajes de respuesta SAML cuando se utiliza Casdoor como proveedor de identidad SAML",
|
"Enable SAML compression - Tooltip": "Si comprimir o no los mensajes de respuesta SAML cuando se utiliza Casdoor como proveedor de identidad SAML",
|
||||||
"Enable side panel": "Habilitar panel lateral",
|
"Enable side panel": "Habilitar panel lateral",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Error de registro",
|
"Sign Up Error": "Error de registro",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Sesión de inicio de sesión",
|
"Signin session": "Sesión de inicio de sesión",
|
||||||
"Signup items": "Artículos de registro",
|
"Signup items": "Artículos de registro",
|
||||||
"Signup items - Tooltip": "Elementos para que los usuarios los completen al registrar nuevas cuentas",
|
"Signup items - Tooltip": "Elementos para que los usuarios los completen al registrar nuevas cuentas",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "La aplicación no permite registrarse una cuenta nueva",
|
"The application does not allow to sign up new account": "La aplicación no permite registrarse una cuenta nueva",
|
||||||
"Token expire": "Token expirado",
|
"Token expire": "Token expirado",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Nombre de la tabla de la tienda de políticas",
|
"Adapter - Tooltip": "Nombre de la tabla de la tienda de políticas",
|
||||||
"Adapters": "Adaptadores",
|
"Adapters": "Adaptadores",
|
||||||
"Add": "Añadir",
|
"Add": "Añadir",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "URL de afiliación",
|
"Affiliation URL": "URL de afiliación",
|
||||||
"Affiliation URL - Tooltip": "La URL de la página de inicio para la afiliación",
|
"Affiliation URL - Tooltip": "La URL de la página de inicio para la afiliación",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "URL personalizado para la página de registro. Si no se establece, se usará la página de registro predeterminada de Casdoor. Cuando se establece, los enlaces de registro en varias páginas de Casdoor redirigirán a esta URL",
|
"Signup URL - Tooltip": "URL personalizado para la página de registro. Si no se establece, se usará la página de registro predeterminada de Casdoor. Cuando se establece, los enlaces de registro en varias páginas de Casdoor redirigirán a esta URL",
|
||||||
"Signup application": "Solicitud de registro",
|
"Signup application": "Solicitud de registro",
|
||||||
"Signup application - Tooltip": "¿A través de qué aplicación se registró el usuario cuando se inscribió?",
|
"Signup application - Tooltip": "¿A través de qué aplicación se registró el usuario cuando se inscribió?",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Lo siento, la página que visitaste no existe.",
|
"Sorry, the page you visited does not exist.": "Lo siento, la página que visitaste no existe.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Lo siento, el usuario que visitaste no existe o no estás autorizado a acceder a este usuario.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Lo siento, el usuario que visitaste no existe o no estás autorizado a acceder a este usuario.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Lo siento, no tiene permiso para acceder a esta página o su estado de inicio de sesión es inválido.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Lo siento, no tiene permiso para acceder a esta página o su estado de inicio de sesión es inválido.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Inicio de sesión automático",
|
"Auto sign in": "Inicio de sesión automático",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continúe con",
|
"Continue with": "Continúe con",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Correo electrónico o teléfono",
|
"Email or phone": "Correo electrónico o teléfono",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Cargando",
|
"Loading": "Cargando",
|
||||||
"Logging out...": "Cerrando sesión...",
|
"Logging out...": "Cerrando sesión...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "¿No tienes cuenta?",
|
"No account?": "¿No tienes cuenta?",
|
||||||
"Or sign in with another account": "O inicia sesión con otra cuenta",
|
"Or sign in with another account": "O inicia sesión con otra cuenta",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Contenido del correo electrónico",
|
"Email content - Tooltip": "Contenido del correo electrónico",
|
||||||
"Email title": "Título del correo electrónico",
|
"Email title": "Título del correo electrónico",
|
||||||
"Email title - Tooltip": "Título del correo electrónico",
|
"Email title - Tooltip": "Título del correo electrónico",
|
||||||
"Enable QR code": "Habilitar código QR",
|
|
||||||
"Enable QR code - Tooltip": "Si permitir el escaneo de códigos QR para acceder",
|
|
||||||
"Endpoint": "Punto final",
|
"Endpoint": "Punto final",
|
||||||
"Endpoint (Intranet)": "Punto final (intranet)",
|
"Endpoint (Intranet)": "Punto final (intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "From address - Tooltip",
|
"From address - Tooltip": "From address - Tooltip",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Analizar los metadatos con éxito",
|
"Parse metadata successfully": "Analizar los metadatos con éxito",
|
||||||
"Path prefix": "Prefijo de ruta",
|
"Path prefix": "Prefijo de ruta",
|
||||||
"Path prefix - Tooltip": "Prefijo de ruta de cubo para almacenamiento de objetos",
|
"Path prefix - Tooltip": "Prefijo de ruta de cubo para almacenamiento de objetos",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Por favor, utiliza WeChat y escanea el código QR para iniciar sesión",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Puerto",
|
"Port": "Puerto",
|
||||||
"Port - Tooltip": "Asegúrate de que el puerto esté abierto",
|
"Port - Tooltip": "Asegúrate de que el puerto esté abierto",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "URL de token",
|
"Token URL - Tooltip": "URL de token",
|
||||||
"Type": "Tipo",
|
"Type": "Tipo",
|
||||||
"Type - Tooltip": "Seleccionar un tipo",
|
"Type - Tooltip": "Seleccionar un tipo",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "Lorsqu'une session connectée existe dans Casdoor, elle est automatiquement utilisée pour la connexion côté application",
|
"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": "URL de fond",
|
||||||
"Background URL - Tooltip": "L'URL de l'image d'arrière-plan utilisée sur la page de connexion",
|
"Background URL - Tooltip": "L'URL de l'image d'arrière-plan utilisée sur la page de connexion",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Fournisseurs liés",
|
"Binding providers": "Fournisseurs liés",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Centré",
|
"Center": "Centré",
|
||||||
"Copy SAML metadata URL": "Copiez l'URL de métadonnées SAML",
|
"Copy SAML metadata URL": "Copiez l'URL de métadonnées SAML",
|
||||||
"Copy prompt page URL": "Copier l'URL de la page de l'invite",
|
"Copy prompt page URL": "Copier l'URL de la page de l'invite",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "Lorsqu'un fournisseur tiers est utilisé pour se connecter, si un compte existe dans l'organisation avec la même adresse e-mail, la méthode de connexion tierce sera automatiquement associée à ce compte",
|
"Enable Email linking - Tooltip": "Lorsqu'un fournisseur tiers est utilisé pour se connecter, si un compte existe dans l'organisation avec la même adresse e-mail, la méthode de connexion tierce sera automatiquement associée à ce compte",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Activer la compression SAML",
|
"Enable SAML compression": "Activer la compression SAML",
|
||||||
"Enable SAML compression - Tooltip": "Compresser ou non les messages de réponse SAML lorsque Casdoor est utilisé en tant que fournisseur d'identité SAML",
|
"Enable SAML compression - Tooltip": "Compresser ou non les messages de réponse SAML lorsque Casdoor est utilisé en tant que fournisseur d'identité SAML",
|
||||||
"Enable side panel": "Activer le panneau latéral",
|
"Enable side panel": "Activer le panneau latéral",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Erreur d'inscription",
|
"Sign Up Error": "Erreur d'inscription",
|
||||||
"Signin": "Connexion",
|
"Signin": "Connexion",
|
||||||
"Signin (Default True)": "Connexion (Vrai par défaut)",
|
"Signin (Default True)": "Connexion (Vrai par défaut)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Session de connexion",
|
"Signin session": "Session de connexion",
|
||||||
"Signup items": "Champs d'inscription",
|
"Signup items": "Champs d'inscription",
|
||||||
"Signup items - Tooltip": "Champs à remplir lors de l'enregistrement de nouveaux comptes",
|
"Signup items - Tooltip": "Champs à remplir lors de l'enregistrement de nouveaux comptes",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Seuls les comptes ayant leur étiquette listée dans les étiquettes de l'application peuvent se connecter",
|
"Tags - Tooltip": "Seuls les comptes ayant leur étiquette listée dans les étiquettes de l'application peuvent se connecter",
|
||||||
"The application does not allow to sign up new account": "L'application ne permet pas de créer un nouveau compte",
|
"The application does not allow to sign up new account": "L'application ne permet pas de créer un nouveau compte",
|
||||||
"Token expire": "Expiration du jeton",
|
"Token expire": "Expiration du jeton",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Nom de la table du magasin de règle",
|
"Adapter - Tooltip": "Nom de la table du magasin de règle",
|
||||||
"Adapters": "Adaptateurs",
|
"Adapters": "Adaptateurs",
|
||||||
"Add": "Ajouter",
|
"Add": "Ajouter",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Administration",
|
"Admin": "Administration",
|
||||||
"Affiliation URL": "URL d'affiliation",
|
"Affiliation URL": "URL d'affiliation",
|
||||||
"Affiliation URL - Tooltip": "URL du site web de l'affiliation",
|
"Affiliation URL - Tooltip": "URL du site web de l'affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "URL personnalisée pour la page d'inscription. Si elle n'est pas définie, la page d'inscription par défaut de Casdoor utilisée. Lorsqu'elle est définie, les liens d'inscription sur les différentes pages de Casdoor redirigeront vers cette URL",
|
"Signup URL - Tooltip": "URL personnalisée pour la page d'inscription. Si elle n'est pas définie, la page d'inscription par défaut de Casdoor utilisée. Lorsqu'elle est définie, les liens d'inscription sur les différentes pages de Casdoor redirigeront vers cette URL",
|
||||||
"Signup application": "Application d'inscription",
|
"Signup application": "Application d'inscription",
|
||||||
"Signup application - Tooltip": "L'application utilisée lors de la création du compte",
|
"Signup application - Tooltip": "L'application utilisée lors de la création du compte",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Désolé, la page que vous avez visitée n'existe pas.",
|
"Sorry, the page you visited does not exist.": "Désolé, la page que vous avez visitée n'existe pas.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Désolé, le compte que vous avez visité n'existe pas ou vous n'êtes pas autorisé à accéder à ce compte.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Désolé, le compte que vous avez visité n'existe pas ou vous n'êtes pas autorisé à accéder à ce compte.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Désolé, vous n'avez pas la permission d'accéder à cette page ou votre statut de connexion est invalide.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Désolé, vous n'avez pas la permission d'accéder à cette page ou votre statut de connexion est invalide.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Connexion automatique",
|
"Auto sign in": "Connexion automatique",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continuer avec",
|
"Continue with": "Continuer avec",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email ou téléphone",
|
"Email or phone": "Email ou téléphone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Chargement",
|
"Loading": "Chargement",
|
||||||
"Logging out...": "Déconnexion...",
|
"Logging out...": "Déconnexion...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "Le plugin MetaMask n'a pas été détecté",
|
"MetaMask plugin not detected": "Le plugin MetaMask n'a pas été détecté",
|
||||||
"No account?": "Pas de compte ?",
|
"No account?": "Pas de compte ?",
|
||||||
"Or sign in with another account": "Ou connectez-vous avec un autre compte",
|
"Or sign in with another account": "Ou connectez-vous avec un autre compte",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Contenu de l'e-mail",
|
"Email content - Tooltip": "Contenu de l'e-mail",
|
||||||
"Email title": "Titre de l'email",
|
"Email title": "Titre de l'email",
|
||||||
"Email title - Tooltip": "Titre de l'email",
|
"Email title - Tooltip": "Titre de l'email",
|
||||||
"Enable QR code": "Activer le code QR",
|
|
||||||
"Enable QR code - Tooltip": "Permettre de scanner un QR code pour se connecter",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (intranet)",
|
"Endpoint (Intranet)": "Endpoint (intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Infobulle",
|
"Endpoint - Tooltip": "Endpoint - Infobulle",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "Adresse de l'expéditeur",
|
"From address": "Adresse de l'expéditeur",
|
||||||
"From address - Tooltip": "L'adresse e-mail affichée comme expéditeur dans les e-mails envoyés",
|
"From address - Tooltip": "L'adresse e-mail affichée comme expéditeur dans les e-mails envoyés",
|
||||||
"From name": "Nom de l'expéditeur",
|
"From name": "Nom de l'expéditeur",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parcourir les métadonnées avec succès",
|
"Parse metadata successfully": "Parcourir les métadonnées avec succès",
|
||||||
"Path prefix": "Préfixe de chemin",
|
"Path prefix": "Préfixe de chemin",
|
||||||
"Path prefix - Tooltip": "Préfixe de chemin de seau pour le stockage d'objet",
|
"Path prefix - Tooltip": "Préfixe de chemin de seau pour le stockage d'objet",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Veuillez utiliser WeChat et scanner le code QR pour vous connecter",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Assurez-vous que le port est ouvert",
|
"Port - Tooltip": "Assurez-vous que le port est ouvert",
|
||||||
"Private Key": "Clé privée",
|
"Private Key": "Clé privée",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "URL de jeton",
|
"Token URL - Tooltip": "URL de jeton",
|
||||||
"Type": "Type de texte",
|
"Type": "Type de texte",
|
||||||
"Type - Tooltip": "Sélectionnez un type",
|
"Type - Tooltip": "Sélectionnez un type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "Association de compte",
|
"User mapping": "Association de compte",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "Ketika sesi masuk yang terdaftar ada di Casdoor, secara otomatis digunakan untuk masuk ke sisi aplikasi",
|
"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": "URL latar belakang",
|
||||||
"Background URL - Tooltip": "URL dari gambar latar belakang yang digunakan di halaman login",
|
"Background URL - Tooltip": "URL dari gambar latar belakang yang digunakan di halaman login",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "pusat",
|
"Center": "pusat",
|
||||||
"Copy SAML metadata URL": "Salin URL metadata SAML",
|
"Copy SAML metadata URL": "Salin URL metadata SAML",
|
||||||
"Copy prompt page URL": "Salin URL halaman prompt",
|
"Copy prompt page URL": "Salin URL halaman prompt",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "Ketika menggunakan penyedia layanan pihak ketiga untuk masuk, jika ada pengguna di organisasi dengan email yang sama, metode login pihak ketiga akan secara otomatis terhubung dengan pengguna tersebut",
|
"Enable Email linking - Tooltip": "Ketika menggunakan penyedia layanan pihak ketiga untuk masuk, jika ada pengguna di organisasi dengan email yang sama, metode login pihak ketiga akan secara otomatis terhubung dengan pengguna tersebut",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Aktifkan kompresi SAML",
|
"Enable SAML compression": "Aktifkan kompresi SAML",
|
||||||
"Enable SAML compression - Tooltip": "Apakah pesan respons SAML harus dikompres saat Casdoor digunakan sebagai SAML idp?",
|
"Enable SAML compression - Tooltip": "Apakah pesan respons SAML harus dikompres saat Casdoor digunakan sebagai SAML idp?",
|
||||||
"Enable side panel": "Aktifkan panel samping",
|
"Enable side panel": "Aktifkan panel samping",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Kesalahan Pendaftaran",
|
"Sign Up Error": "Kesalahan Pendaftaran",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Sesi masuk",
|
"Signin session": "Sesi masuk",
|
||||||
"Signup items": "Item pendaftaran",
|
"Signup items": "Item pendaftaran",
|
||||||
"Signup items - Tooltip": "Item-item yang harus diisi pengguna saat mendaftar untuk akun baru",
|
"Signup items - Tooltip": "Item-item yang harus diisi pengguna saat mendaftar untuk akun baru",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"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 untuk mendaftar akun baru",
|
||||||
"Token expire": "Token kadaluarsa",
|
"Token expire": "Token kadaluarsa",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Nama tabel dari penyimpanan kebijakan",
|
"Adapter - Tooltip": "Nama tabel dari penyimpanan kebijakan",
|
||||||
"Adapters": "Adaptor",
|
"Adapters": "Adaptor",
|
||||||
"Add": "Tambahkan",
|
"Add": "Tambahkan",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "URL Afiliasi",
|
"Affiliation URL": "URL Afiliasi",
|
||||||
"Affiliation URL - Tooltip": "URL halaman depan untuk afiliasi",
|
"Affiliation URL - Tooltip": "URL halaman depan untuk afiliasi",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "URL kustom untuk halaman pendaftaran. Jika tidak diatur, halaman pendaftaran Casdoor default akan digunakan. Ketika diatur, tautan pendaftaran pada berbagai halaman Casdoor akan dialihkan ke URL ini",
|
"Signup URL - Tooltip": "URL kustom untuk halaman pendaftaran. Jika tidak diatur, halaman pendaftaran Casdoor default akan digunakan. Ketika diatur, tautan pendaftaran pada berbagai halaman Casdoor akan dialihkan ke URL ini",
|
||||||
"Signup application": "Pendaftaran aplikasi",
|
"Signup application": "Pendaftaran aplikasi",
|
||||||
"Signup application - Tooltip": "Melalui aplikasi mana pengguna mendaftar saat mereka mendaftar",
|
"Signup application - Tooltip": "Melalui aplikasi mana pengguna mendaftar saat mereka mendaftar",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Maaf, halaman yang Anda kunjungi tidak ada.",
|
"Sorry, the page you visited does not exist.": "Maaf, halaman yang Anda kunjungi tidak ada.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Maaf, pengguna yang Anda kunjungi tidak ada atau Anda tidak diizinkan untuk mengakses pengguna ini.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Maaf, pengguna yang Anda kunjungi tidak ada atau Anda tidak diizinkan untuk mengakses pengguna ini.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Maaf, Anda tidak memiliki izin untuk mengakses halaman ini atau status masuk tidak valid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Maaf, Anda tidak memiliki izin untuk mengakses halaman ini atau status masuk tidak valid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Masuk otomatis",
|
"Auto sign in": "Masuk otomatis",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Lanjutkan dengan",
|
"Continue with": "Lanjutkan dengan",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email atau telepon",
|
"Email or phone": "Email atau telepon",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Memuat",
|
"Loading": "Memuat",
|
||||||
"Logging out...": "Keluar...",
|
"Logging out...": "Keluar...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "Tidak memiliki akun?",
|
"No account?": "Tidak memiliki akun?",
|
||||||
"Or sign in with another account": "Atau masuk dengan akun lain",
|
"Or sign in with another account": "Atau masuk dengan akun lain",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Isi Email",
|
"Email content - Tooltip": "Isi Email",
|
||||||
"Email title": "Judul Email",
|
"Email title": "Judul Email",
|
||||||
"Email title - Tooltip": "Judul email",
|
"Email title - Tooltip": "Judul email",
|
||||||
"Enable QR code": "Aktifkan kode QR",
|
|
||||||
"Enable QR code - Tooltip": "Apakah diizinkan untuk memindai kode QR untuk masuk?",
|
|
||||||
"Endpoint": "Titik akhir",
|
"Endpoint": "Titik akhir",
|
||||||
"Endpoint (Intranet)": "Titik Akhir (Intranet)",
|
"Endpoint (Intranet)": "Titik Akhir (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "From address - Tooltip",
|
"From address - Tooltip": "From address - Tooltip",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Berhasil mem-parse metadata",
|
"Parse metadata successfully": "Berhasil mem-parse metadata",
|
||||||
"Path prefix": "Awalan jalur",
|
"Path prefix": "Awalan jalur",
|
||||||
"Path prefix - Tooltip": "Awalan path ember untuk penyimpanan objek dalam bucket",
|
"Path prefix - Tooltip": "Awalan path ember untuk penyimpanan objek dalam bucket",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Silakan gunakan WeChat dan pindai kode QR untuk masuk",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Pelabuhan",
|
"Port": "Pelabuhan",
|
||||||
"Port - Tooltip": "Pastikan port terbuka",
|
"Port - Tooltip": "Pastikan port terbuka",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL: URL Token",
|
"Token URL - Tooltip": "Token URL: URL Token",
|
||||||
"Type": "Jenis",
|
"Type": "Jenis",
|
||||||
"Type - Tooltip": "Pilih tipe",
|
"Type - Tooltip": "Pilih tipe",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "Quando una sessione esiste in Casdoor, viene utilizzata automaticamente per il login lato applicazione",
|
"Auto signin - Tooltip": "Quando una sessione esiste in Casdoor, viene utilizzata automaticamente per il login lato applicazione",
|
||||||
"Background URL": "Background URL",
|
"Background URL": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "Casdoorにログインセッションが存在する場合、アプリケーション側のログインに自動的に使用されます",
|
"Auto signin - Tooltip": "Casdoorにログインセッションが存在する場合、アプリケーション側のログインに自動的に使用されます",
|
||||||
"Background URL": "背景URL",
|
"Background URL": "背景URL",
|
||||||
"Background URL - Tooltip": "ログインページで使用される背景画像のURL",
|
"Background URL - Tooltip": "ログインページで使用される背景画像のURL",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "センター",
|
"Center": "センター",
|
||||||
"Copy SAML metadata URL": "SAMLメタデータのURLをコピーしてください",
|
"Copy SAML metadata URL": "SAMLメタデータのURLをコピーしてください",
|
||||||
"Copy prompt page URL": "プロンプトページのURLをコピーしてください",
|
"Copy prompt page URL": "プロンプトページのURLをコピーしてください",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "組織内に同じメールアドレスを持つユーザーがいる場合、サードパーティのログイン方法は自動的にそのユーザーに関連付けられます",
|
"Enable Email linking - Tooltip": "組織内に同じメールアドレスを持つユーザーがいる場合、サードパーティのログイン方法は自動的にそのユーザーに関連付けられます",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "SAMLの圧縮を有効にする",
|
"Enable SAML compression": "SAMLの圧縮を有効にする",
|
||||||
"Enable SAML compression - Tooltip": "CasdoorをSAML IdPとして使用する場合、SAMLレスポンスメッセージを圧縮するかどうか。圧縮する: 圧縮するかどうか。圧縮しない: 圧縮しないかどうか",
|
"Enable SAML compression - Tooltip": "CasdoorをSAML IdPとして使用する場合、SAMLレスポンスメッセージを圧縮するかどうか。圧縮する: 圧縮するかどうか。圧縮しない: 圧縮しないかどうか",
|
||||||
"Enable side panel": "サイドパネルを有効にする",
|
"Enable side panel": "サイドパネルを有効にする",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "サインアップエラー",
|
"Sign Up Error": "サインアップエラー",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "サインインセッション",
|
"Signin session": "サインインセッション",
|
||||||
"Signup items": "サインアップアイテム",
|
"Signup items": "サインアップアイテム",
|
||||||
"Signup items - Tooltip": "新しいアカウントを登録する際にユーザーが入力するアイテム",
|
"Signup items - Tooltip": "新しいアカウントを登録する際にユーザーが入力するアイテム",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "アプリケーションでは新しいアカウントの登録ができません",
|
"The application does not allow to sign up new account": "アプリケーションでは新しいアカウントの登録ができません",
|
||||||
"Token expire": "トークンの有効期限が切れました",
|
"Token expire": "トークンの有効期限が切れました",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "ポリシー・ストアのテーブル名",
|
"Adapter - Tooltip": "ポリシー・ストアのテーブル名",
|
||||||
"Adapters": "アダプター",
|
"Adapters": "アダプター",
|
||||||
"Add": "追加",
|
"Add": "追加",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "所属するURL",
|
"Affiliation URL": "所属するURL",
|
||||||
"Affiliation URL - Tooltip": "所属先のホームページURL",
|
"Affiliation URL - Tooltip": "所属先のホームページURL",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "登録ページのカスタムURL。設定されていない場合、デフォルトのCasdoor登録ページが使用されます。設定された場合、Casdoorのさまざまなページの登録リンクはこのURLにリダイレクトされます",
|
"Signup URL - Tooltip": "登録ページのカスタムURL。設定されていない場合、デフォルトのCasdoor登録ページが使用されます。設定された場合、Casdoorのさまざまなページの登録リンクはこのURLにリダイレクトされます",
|
||||||
"Signup application": "サインアップ申請書",
|
"Signup application": "サインアップ申請書",
|
||||||
"Signup application - Tooltip": "ユーザーが登録した際に、どのアプリケーションを使用しましたか?",
|
"Signup application - Tooltip": "ユーザーが登録した際に、どのアプリケーションを使用しましたか?",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "申し訳ありませんが、ご訪問いただいたページは存在しません。",
|
"Sorry, the page you visited does not exist.": "申し訳ありませんが、ご訪問いただいたページは存在しません。",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "すみません、あなたが訪問したユーザーは存在しないか、またはそのユーザーにアクセスする権限がありません。",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "すみません、あなたが訪問したユーザーは存在しないか、またはそのユーザーにアクセスする権限がありません。",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "申し訳ありませんが、このページにアクセスする権限がありません、またはログイン状態が無効です。",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "申し訳ありませんが、このページにアクセスする権限がありません、またはログイン状態が無効です。",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "自動サインイン",
|
"Auto sign in": "自動サインイン",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "続ける",
|
"Continue with": "続ける",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "メールまたは電話",
|
"Email or phone": "メールまたは電話",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "ローディング",
|
"Loading": "ローディング",
|
||||||
"Logging out...": "ログアウト中...",
|
"Logging out...": "ログアウト中...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "アカウントがありませんか?",
|
"No account?": "アカウントがありませんか?",
|
||||||
"Or sign in with another account": "別のアカウントでサインインする",
|
"Or sign in with another account": "別のアカウントでサインインする",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "メールの内容",
|
"Email content - Tooltip": "メールの内容",
|
||||||
"Email title": "電子メールのタイトル",
|
"Email title": "電子メールのタイトル",
|
||||||
"Email title - Tooltip": "メールのタイトル",
|
"Email title - Tooltip": "メールのタイトル",
|
||||||
"Enable QR code": "QRコードを有効にする",
|
|
||||||
"Enable QR code - Tooltip": "ログインするためにQRコードをスキャンすることを許可するかどうか",
|
|
||||||
"Endpoint": "エンドポイント",
|
"Endpoint": "エンドポイント",
|
||||||
"Endpoint (Intranet)": "エンドポイント(イントラネット)",
|
"Endpoint (Intranet)": "エンドポイント(イントラネット)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "From address - Tooltip",
|
"From address - Tooltip": "From address - Tooltip",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "メタデータを正常に解析しました",
|
"Parse metadata successfully": "メタデータを正常に解析しました",
|
||||||
"Path prefix": "パスプレフィックス",
|
"Path prefix": "パスプレフィックス",
|
||||||
"Path prefix - Tooltip": "オブジェクトストレージのバケットパスプレフィックス",
|
"Path prefix - Tooltip": "オブジェクトストレージのバケットパスプレフィックス",
|
||||||
"Please use WeChat and scan the QR code to sign in": "WeChatを使用し、QRコードをスキャンしてサインインしてください",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "ポート",
|
"Port": "ポート",
|
||||||
"Port - Tooltip": "ポートが開いていることを確認してください",
|
"Port - Tooltip": "ポートが開いていることを確認してください",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "トークンURL",
|
"Token URL - Tooltip": "トークンURL",
|
||||||
"Type": "タイプ",
|
"Type": "タイプ",
|
||||||
"Type - Tooltip": "タイプを選択してください",
|
"Type - Tooltip": "タイプを選択してください",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "카스도어에 로그인된 세션이 존재할 때, 애플리케이션 쪽 로그인에 자동으로 사용됩니다",
|
"Auto signin - Tooltip": "카스도어에 로그인된 세션이 존재할 때, 애플리케이션 쪽 로그인에 자동으로 사용됩니다",
|
||||||
"Background URL": "배경 URL",
|
"Background URL": "배경 URL",
|
||||||
"Background URL - Tooltip": "로그인 페이지에서 사용된 배경 이미지의 URL",
|
"Background URL - Tooltip": "로그인 페이지에서 사용된 배경 이미지의 URL",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "중앙",
|
"Center": "중앙",
|
||||||
"Copy SAML metadata URL": "SAML 메타데이터 URL 복사",
|
"Copy SAML metadata URL": "SAML 메타데이터 URL 복사",
|
||||||
"Copy prompt page URL": "프롬프트 페이지 URL을 복사하세요",
|
"Copy prompt page URL": "프롬프트 페이지 URL을 복사하세요",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "3rd-party 로그인 공급자를 사용할 때, 만약 조직 내에 동일한 이메일을 사용하는 사용자가 있다면, 3rd-party 로그인 방법은 자동으로 해당 사용자와 연동됩니다",
|
"Enable Email linking - Tooltip": "3rd-party 로그인 공급자를 사용할 때, 만약 조직 내에 동일한 이메일을 사용하는 사용자가 있다면, 3rd-party 로그인 방법은 자동으로 해당 사용자와 연동됩니다",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "SAML 압축 사용 가능하게 설정하기",
|
"Enable SAML compression": "SAML 압축 사용 가능하게 설정하기",
|
||||||
"Enable SAML compression - Tooltip": "카스도어가 SAML idp로 사용될 때 SAML 응답 메시지를 압축할 것인지 여부",
|
"Enable SAML compression - Tooltip": "카스도어가 SAML idp로 사용될 때 SAML 응답 메시지를 압축할 것인지 여부",
|
||||||
"Enable side panel": "측면 패널 활성화",
|
"Enable side panel": "측면 패널 활성화",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "가입 오류",
|
"Sign Up Error": "가입 오류",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "로그인 세션",
|
"Signin session": "로그인 세션",
|
||||||
"Signup items": "가입 항목",
|
"Signup items": "가입 항목",
|
||||||
"Signup items - Tooltip": "새로운 계정 등록시 사용자가 작성해야하는 항목들",
|
"Signup items - Tooltip": "새로운 계정 등록시 사용자가 작성해야하는 항목들",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "이 어플리케이션은 새 계정 등록을 허용하지 않습니다",
|
"The application does not allow to sign up new account": "이 어플리케이션은 새 계정 등록을 허용하지 않습니다",
|
||||||
"Token expire": "토큰 만료",
|
"Token expire": "토큰 만료",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "정책 저장소의 테이블 이름",
|
"Adapter - Tooltip": "정책 저장소의 테이블 이름",
|
||||||
"Adapters": "어댑터",
|
"Adapters": "어댑터",
|
||||||
"Add": "추가하다",
|
"Add": "추가하다",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "소속 URL",
|
"Affiliation URL": "소속 URL",
|
||||||
"Affiliation URL - Tooltip": "소속 홈페이지 URL",
|
"Affiliation URL - Tooltip": "소속 홈페이지 URL",
|
||||||
@@ -233,7 +241,7 @@
|
|||||||
"Found some texts still not translated? Please help us translate at": "아직 번역되지 않은 텍스트가 있나요? 번역에 도움을 주실 수 있나요?",
|
"Found some texts still not translated? Please help us translate at": "아직 번역되지 않은 텍스트가 있나요? 번역에 도움을 주실 수 있나요?",
|
||||||
"Go to enable": "Go to enable",
|
"Go to enable": "Go to enable",
|
||||||
"Go to writable demo site?": "쓰기 가능한 데모 사이트로 이동하시겠습니까?",
|
"Go to writable demo site?": "쓰기 가능한 데모 사이트로 이동하시겠습니까?",
|
||||||
"Groups": "Groups",
|
"Groups": "그룹",
|
||||||
"Groups - Tooltip": "Groups - Tooltip",
|
"Groups - Tooltip": "Groups - Tooltip",
|
||||||
"Home": "집",
|
"Home": "집",
|
||||||
"Home - Tooltip": "어플리케이션 홈 페이지",
|
"Home - Tooltip": "어플리케이션 홈 페이지",
|
||||||
@@ -270,9 +278,9 @@
|
|||||||
"None": "None",
|
"None": "None",
|
||||||
"OAuth providers": "OAuth 공급자",
|
"OAuth providers": "OAuth 공급자",
|
||||||
"OK": "예",
|
"OK": "예",
|
||||||
"Organization": "조직화",
|
"Organization": "조직",
|
||||||
"Organization - Tooltip": "각 사용자와 애플리케이션은 테넌트나 사용자 풀과 유사한 개념으로, 조직에 속합니다",
|
"Organization - Tooltip": "각 사용자와 애플리케이션은 테넌트나 사용자 풀과 유사한 개념으로, 조직에 속합니다",
|
||||||
"Organizations": "조직들",
|
"Organizations": "조직",
|
||||||
"Password": "비밀번호",
|
"Password": "비밀번호",
|
||||||
"Password - Tooltip": "비밀번호가 올바른지 확인하세요",
|
"Password - Tooltip": "비밀번호가 올바른지 확인하세요",
|
||||||
"Password complexity options": "Password complexity options",
|
"Password complexity options": "Password complexity options",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "등록 페이지를 위한 사용자 정의 URL입니다. 설정되지 않은 경우 기본 Casdoor 등록 페이지가 사용됩니다. 설정하면 Casdoor의 다양한 페이지에서 등록 링크가 이 URL로 리디렉션됩니다",
|
"Signup URL - Tooltip": "등록 페이지를 위한 사용자 정의 URL입니다. 설정되지 않은 경우 기본 Casdoor 등록 페이지가 사용됩니다. 설정하면 Casdoor의 다양한 페이지에서 등록 링크가 이 URL로 리디렉션됩니다",
|
||||||
"Signup application": "가입 양식",
|
"Signup application": "가입 양식",
|
||||||
"Signup application - Tooltip": "사용자가 가입할 때 등록한 어플리케이션은 무엇인가요?",
|
"Signup application - Tooltip": "사용자가 가입할 때 등록한 어플리케이션은 무엇인가요?",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "죄송합니다. 방문하신 페이지는 존재하지 않습니다.",
|
"Sorry, the page you visited does not exist.": "죄송합니다. 방문하신 페이지는 존재하지 않습니다.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "죄송합니다. 방문하신 사용자가 존재하지 않거나 사용자에게 접근할 권한이 없습니다.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "죄송합니다. 방문하신 사용자가 존재하지 않거나 사용자에게 접근할 권한이 없습니다.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "죄송합니다. 이 페이지에 접근할 권한이 없거나 로그인 상태가 유효하지 않습니다.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "죄송합니다. 이 페이지에 접근할 권한이 없거나 로그인 상태가 유효하지 않습니다.",
|
||||||
@@ -361,7 +370,7 @@
|
|||||||
"User containers": "사용자 풀",
|
"User containers": "사용자 풀",
|
||||||
"User type": "사용자 유형",
|
"User type": "사용자 유형",
|
||||||
"User type - Tooltip": "사용자가 속한 태그는 기본적으로 \"보통 사용자\"로 설정됩니다",
|
"User type - Tooltip": "사용자가 속한 태그는 기본적으로 \"보통 사용자\"로 설정됩니다",
|
||||||
"Users": "사용자들",
|
"Users": "사용자",
|
||||||
"Users under all organizations": "모든 조직의 사용자",
|
"Users under all organizations": "모든 조직의 사용자",
|
||||||
"Webhooks": "Webhooks",
|
"Webhooks": "Webhooks",
|
||||||
"You can only select one physical group": "You can only select one physical group",
|
"You can only select one physical group": "You can only select one physical group",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "자동 로그인",
|
"Auto sign in": "자동 로그인",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "계속하다",
|
"Continue with": "계속하다",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "이메일 또는 전화",
|
"Email or phone": "이메일 또는 전화",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "로딩 중입니다",
|
"Loading": "로딩 중입니다",
|
||||||
"Logging out...": "로그아웃 중...",
|
"Logging out...": "로그아웃 중...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "계정이 없나요?",
|
"No account?": "계정이 없나요?",
|
||||||
"Or sign in with another account": "다른 계정으로 로그인하세요",
|
"Or sign in with another account": "다른 계정으로 로그인하세요",
|
||||||
@@ -521,7 +534,7 @@
|
|||||||
"Is profile public - Tooltip": "닫힌 후에는 전역 관리자 또는 동일한 조직의 사용자만 사용자 프로필 페이지에 액세스할 수 있습니다",
|
"Is profile public - Tooltip": "닫힌 후에는 전역 관리자 또는 동일한 조직의 사용자만 사용자 프로필 페이지에 액세스할 수 있습니다",
|
||||||
"Modify rule": "규칙 수정",
|
"Modify rule": "규칙 수정",
|
||||||
"New Organization": "새로운 조직",
|
"New Organization": "새로운 조직",
|
||||||
"Optional": "Optional",
|
"Optional": "선택사항",
|
||||||
"Prompt": "Prompt",
|
"Prompt": "Prompt",
|
||||||
"Required": "Required",
|
"Required": "Required",
|
||||||
"Soft deletion": "소프트 삭제",
|
"Soft deletion": "소프트 삭제",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "이메일 내용",
|
"Email content - Tooltip": "이메일 내용",
|
||||||
"Email title": "이메일 제목",
|
"Email title": "이메일 제목",
|
||||||
"Email title - Tooltip": "이메일 제목",
|
"Email title - Tooltip": "이메일 제목",
|
||||||
"Enable QR code": "QR 코드 활성화",
|
|
||||||
"Enable QR code - Tooltip": "QR 코드를 스캔해서 로그인할 수 있는지 여부",
|
|
||||||
"Endpoint": "엔드포인트",
|
"Endpoint": "엔드포인트",
|
||||||
"Endpoint (Intranet)": "엔드포인트 (Intranet)",
|
"Endpoint (Intranet)": "엔드포인트 (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "From address - Tooltip",
|
"From address - Tooltip": "From address - Tooltip",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "메타데이터를 성공적으로 분석했습니다",
|
"Parse metadata successfully": "메타데이터를 성공적으로 분석했습니다",
|
||||||
"Path prefix": "경로 접두어",
|
"Path prefix": "경로 접두어",
|
||||||
"Path prefix - Tooltip": "객체 저장소에 대한 버킷 경로 접두어",
|
"Path prefix - Tooltip": "객체 저장소에 대한 버킷 경로 접두어",
|
||||||
"Please use WeChat and scan the QR code to sign in": "WeChat를 사용하시고 QR 코드를 스캔하여 로그인해주세요",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "포트",
|
"Port": "포트",
|
||||||
"Port - Tooltip": "포트가 열려 있는지 확인하세요",
|
"Port - Tooltip": "포트가 열려 있는지 확인하세요",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "토큰 URL",
|
"Token URL - Tooltip": "토큰 URL",
|
||||||
"Type": "타입",
|
"Type": "타입",
|
||||||
"Type - Tooltip": "유형을 선택하세요",
|
"Type - Tooltip": "유형을 선택하세요",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
@@ -854,7 +871,7 @@
|
|||||||
"New Role": "새로운 역할",
|
"New Role": "새로운 역할",
|
||||||
"Sub domains": "하위 도메인",
|
"Sub domains": "하위 도메인",
|
||||||
"Sub domains - Tooltip": "현재 역할에 포함된 도메인",
|
"Sub domains - Tooltip": "현재 역할에 포함된 도메인",
|
||||||
"Sub groups": "Sub groups",
|
"Sub groups": "하위 그룹",
|
||||||
"Sub groups - Tooltip": "Sub groups - Tooltip",
|
"Sub groups - Tooltip": "Sub groups - Tooltip",
|
||||||
"Sub roles": "서브 역할",
|
"Sub roles": "서브 역할",
|
||||||
"Sub roles - Tooltip": "현재 역할에 포함된 역할",
|
"Sub roles - Tooltip": "현재 역할에 포함된 역할",
|
||||||
|
@@ -22,7 +22,9 @@
|
|||||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
"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": "Background URL",
|
||||||
"Background URL - Tooltip": "URL of the background image used in the login page",
|
"Background URL - Tooltip": "URL of the background image used in the login page",
|
||||||
|
"Big icon": "Big icon",
|
||||||
"Binding providers": "Binding providers",
|
"Binding providers": "Binding providers",
|
||||||
|
"CSS style": "CSS style",
|
||||||
"Center": "Center",
|
"Center": "Center",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
"Enable Email linking - Tooltip": "When using 3rd-party providers to log in, if there is a user in the organization with the same Email, the 3rd-party login method will be automatically associated with that user",
|
||||||
"Enable SAML C14N10": "Enable SAML C14N10",
|
"Enable SAML C14N10": "Enable SAML C14N10",
|
||||||
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
"Enable SAML C14N10 - Tooltip": "Enable SAML C14N10 - Tooltip",
|
||||||
|
"Enable SAML POST binding": "Enable SAML POST binding",
|
||||||
|
"Enable SAML POST binding - Tooltip": "The HTTP POST binding uses input fields in a HTML form to send SAML messages, Enable when your SP use it",
|
||||||
"Enable SAML compression": "Enable SAML compression",
|
"Enable SAML compression": "Enable SAML compression",
|
||||||
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
"Enable SAML compression - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Enable side panel",
|
||||||
@@ -93,11 +97,14 @@
|
|||||||
"Sign Up Error": "Sign Up Error",
|
"Sign Up Error": "Sign Up Error",
|
||||||
"Signin": "Signin",
|
"Signin": "Signin",
|
||||||
"Signin (Default True)": "Signin (Default True)",
|
"Signin (Default True)": "Signin (Default True)",
|
||||||
|
"Signin items": "Signin items",
|
||||||
|
"Signin items - Tooltip": "Signin items - Tooltip",
|
||||||
"Signin methods": "Signin methods",
|
"Signin methods": "Signin methods",
|
||||||
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
"Signin methods - Tooltip": "Signin methods - Tooltip",
|
||||||
"Signin session": "Signin session",
|
"Signin session": "Signin session",
|
||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
|
"Small icon": "Small icon",
|
||||||
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
@@ -167,6 +174,7 @@
|
|||||||
"Adapter - Tooltip": "Table name of the policy store",
|
"Adapter - Tooltip": "Table name of the policy store",
|
||||||
"Adapters": "Adapters",
|
"Adapters": "Adapters",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"Add custom item": "Add custom item",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Affiliation URL": "Affiliation URL",
|
"Affiliation URL": "Affiliation URL",
|
||||||
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
|
||||||
@@ -325,6 +333,7 @@
|
|||||||
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
"Signup URL - Tooltip": "Custom URL for the registration page. If not set, the default Casdoor registration page will be used. When set, the registration links on various Casdoor pages will redirect to this URL",
|
||||||
"Signup application": "Signup application",
|
"Signup application": "Signup application",
|
||||||
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
"Signup application - Tooltip": "Which application the user registered through when they signed up",
|
||||||
|
"Signup link": "Signup link",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
@@ -388,6 +397,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
@@ -427,6 +438,7 @@
|
|||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"Auto sign in": "Auto sign in",
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Back button": "Back button",
|
||||||
"Continue with": "Continue with",
|
"Continue with": "Continue with",
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Email or phone": "Email or phone",
|
"Email or phone": "Email or phone",
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
"LDAP username, Email or phone": "LDAP username, Email or phone",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Logging out...": "Logging out...",
|
"Logging out...": "Logging out...",
|
||||||
|
"Login button": "Login button",
|
||||||
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
"MetaMask plugin not detected": "MetaMask plugin not detected",
|
||||||
"No account?": "No account?",
|
"No account?": "No account?",
|
||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
@@ -721,11 +734,11 @@
|
|||||||
"Email content - Tooltip": "Content of the Email",
|
"Email content - Tooltip": "Content of the Email",
|
||||||
"Email title": "Email title",
|
"Email title": "Email title",
|
||||||
"Email title - Tooltip": "Title of the email",
|
"Email title - Tooltip": "Title of the email",
|
||||||
"Enable QR code": "Enable QR code",
|
|
||||||
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
|
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "Endpoint",
|
||||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
"Endpoint - Tooltip": "Endpoint - Tooltip",
|
||||||
|
"Follow-up action": "Follow-up action",
|
||||||
|
"Follow-up action - Tooltip": "If you choose \"Use WeChat Open Platform to login\", users need to login on the WeChat Open Platform after following the wechat official account.",
|
||||||
"From address": "From address",
|
"From address": "From address",
|
||||||
"From address - Tooltip": "Email address of \"From\"",
|
"From address - Tooltip": "Email address of \"From\"",
|
||||||
"From name": "From name",
|
"From name": "From name",
|
||||||
@@ -753,7 +766,7 @@
|
|||||||
"Parse metadata successfully": "Parse metadata successfully",
|
"Parse metadata successfully": "Parse metadata successfully",
|
||||||
"Path prefix": "Path prefix",
|
"Path prefix": "Path prefix",
|
||||||
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
"Path prefix - Tooltip": "Bucket path prefix for object storage",
|
||||||
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
"Please use WeChat to scan the QR code and follow the official account for sign in": "Please use WeChat to scan the QR code and follow the official account for sign in",
|
||||||
"Port": "Port",
|
"Port": "Port",
|
||||||
"Port - Tooltip": "Make sure the port is open",
|
"Port - Tooltip": "Make sure the port is open",
|
||||||
"Private Key": "Private Key",
|
"Private Key": "Private Key",
|
||||||
@@ -831,6 +844,10 @@
|
|||||||
"Token URL - Tooltip": "Token URL",
|
"Token URL - Tooltip": "Token URL",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Type - Tooltip": "Select a type",
|
"Type - Tooltip": "Select a type",
|
||||||
|
"Use WeChat Media Platform in PC": "Use WeChat Media Platform in PC",
|
||||||
|
"Use WeChat Media Platform in PC - Tooltip": "Whether to allow scanning WeChat Media Platform QR code to login",
|
||||||
|
"Use WeChat Media Platform to login": "Use WeChat Media Platform to login",
|
||||||
|
"Use WeChat Open Platform to login": "Use WeChat Open Platform to login",
|
||||||
"User flow": "User flow",
|
"User flow": "User flow",
|
||||||
"User flow - Tooltip": "User flow - Tooltip",
|
"User flow - Tooltip": "User flow - Tooltip",
|
||||||
"User mapping": "User mapping",
|
"User mapping": "User mapping",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user