Compare commits

...

12 Commits

Author SHA1 Message Date
6da452d7e0 feat: show language widget in signup and signin pages (#1180) 2022-10-03 22:40:19 +08:00
5abcf913e6 Fix language menu 2022-10-03 22:39:10 +08:00
58455e688e Improve WebAuthnCredentialTable and border radius 2022-10-03 18:46:40 +08:00
4d6f68eddc Improve footer and color 2022-10-03 17:43:19 +08:00
67f3c5a489 Add verificationCode to login method 2022-10-03 15:41:20 +08:00
9c48582e0c feat: fix bugs in webauthn (#1173) 2022-10-01 11:10:55 +08:00
645c631db9 fix: fix the delete file vulnerability issue (#1174) 2022-10-01 00:33:27 +08:00
3128e68df4 Add sendSilentSigninData() 2022-09-30 01:51:58 +08:00
2247c6a883 Add isSelf() in user edit page 2022-09-29 22:24:05 +08:00
04709f731b Update beego to v1.12.11 2022-09-29 19:45:17 +08:00
ebe1887e8b feat: add saml provider error (#1168)
* fix: add saml provider error

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* fix: search

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>
2022-09-28 21:09:39 +08:00
a7a8805713 feat: fix dulpicate go routines (#1167)
* feat:Support simple ldap server

* fix:fix review problems

* fix:fix review problems

* fix: fix ldapserver crash bug

* Update ldapserver.go

* fix: fix dulpicate go routines

* fix gofumpt problems
2022-09-28 20:28:00 +08:00
58 changed files with 268 additions and 245 deletions

View File

@ -21,7 +21,7 @@ import (
"strconv"
"strings"
"github.com/astaxie/beego"
"github.com/beego/beego"
)
func init() {

View File

@ -18,7 +18,7 @@ import (
"os"
"testing"
"github.com/astaxie/beego"
"github.com/beego/beego"
"github.com/stretchr/testify/assert"
)

View File

@ -18,7 +18,7 @@ import (
"encoding/json"
"fmt"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,8 +18,8 @@ import (
"strings"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/beego/beego"
"github.com/beego/beego/logs"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,9 +17,6 @@ package controllers
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/object"
@ -35,17 +32,7 @@ func StartLdapServer() {
routes.Search(handleSearch).Label(" SEARCH****")
server.Handle(routes)
go server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
// When CTRL+C, SIGINT and SIGTERM signal occurs
// Then stop server gracefully
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch
close(ch)
server.Stop()
server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
}
func handleBind(w ldapserver.ResponseWriter, m *ldapserver.Message) {

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,7 +18,7 @@ import (
"encoding/json"
"fmt"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,7 +18,7 @@ import (
"encoding/json"
"fmt"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -22,7 +22,7 @@ import (
"mime"
"path/filepath"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,7 +18,7 @@ import (
"encoding/json"
"net/http"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -19,7 +19,7 @@ import (
"fmt"
"strings"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -16,6 +16,7 @@ package controllers
import (
"bytes"
"fmt"
"io"
"github.com/casdoor/casdoor/object"
@ -100,7 +101,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
userName := c.Input().Get("name")
user := object.GetUserByFields(userOwner, userName)
if user == nil {
c.ResponseError("Please Giveout Owner and Username.")
c.ResponseError(fmt.Sprintf("The user: %s/%s doesn't exist", userOwner, userName))
return
}
options, sessionData, err := webauthnObj.BeginLogin(user)
@ -121,6 +122,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
// @Success 200 {object} Response "The Response object"
// @router /webauthn/signin/finish [post]
func (c *ApiController) WebAuthnSigninFinish() {
responseType := c.Input().Get("responseType")
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
sessionObj := c.GetSession("authentication")
sessionData, ok := sessionObj.(webauthn.SessionData)
@ -138,5 +140,11 @@ func (c *ApiController) WebAuthnSigninFinish() {
}
c.SetSessionUsername(userId)
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
c.ResponseOk(userId)
application := object.GetApplicationByUser(user)
var form RequestForm
form.Type = responseType
resp := c.HandleLoggedIn(application, user, &form)
c.Data["json"] = resp
c.ServeJSON()
}

View File

@ -17,7 +17,7 @@ package controllers
import (
"encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

2
go.mod
View File

@ -5,8 +5,8 @@ go 1.16
require (
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
github.com/astaxie/beego v1.12.3
github.com/aws/aws-sdk-go v1.44.4
github.com/beego/beego v1.12.11
github.com/beevik/etree v1.1.0
github.com/casbin/casbin/v2 v2.30.1
github.com/casbin/xorm-adapter/v3 v3.0.1

17
go.sum
View File

@ -74,13 +74,13 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1075/go.mod h1:pUKYbK5JQ+1Dfxk80P0q
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ=
github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.44.4 h1:ePN0CVJMdiz2vYUcJH96eyxRrtKGSDMgyhP6rah2OgE=
github.com/aws/aws-sdk-go v1.44.4/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beego/beego v1.12.11 h1:MWKcnpavb7iAIS0m6uuEq6pHKkYvGNw/5umIUKqL7jM=
github.com/beego/beego v1.12.11/go.mod h1:QURFL1HldOcCZAxnc1cZ7wrplsYR5dKPHFjmk6WkLAs=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
@ -115,9 +115,9 @@ github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1C
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -341,7 +341,6 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -412,7 +411,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
@ -430,7 +428,7 @@ github.com/twilio/twilio-go v0.26.0/go.mod h1:lz62Hopu4vicpQ056H5TJ0JE4AP0rS3sQ3
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -458,6 +456,7 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@ -566,6 +565,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -597,6 +597,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -18,9 +18,9 @@ import (
"flag"
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
_ "github.com/astaxie/beego/session/redis"
"github.com/beego/beego"
"github.com/beego/beego/logs"
_ "github.com/beego/beego/session/redis"
"github.com/casdoor/casdoor/authz"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/controllers"

View File

@ -18,7 +18,7 @@ import (
"fmt"
"runtime"
"github.com/astaxie/beego"
"github.com/beego/beego"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
_ "github.com/denisenkom/go-mssqldb" // db = mssql

View File

@ -19,7 +19,7 @@ import (
"fmt"
"strings"
"github.com/astaxie/beego"
"github.com/beego/beego"
"github.com/casdoor/casdoor/util"
goldap "github.com/go-ldap/ldap/v3"
"github.com/thanhpk/randstr"

View File

@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/astaxie/beego/logs"
"github.com/beego/beego/logs"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,7 +18,7 @@ import (
"fmt"
"strings"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
)

View File

@ -127,6 +127,11 @@ func UploadFileSafe(provider *Provider, fullFilePath string, fileBuffer *bytes.B
}
func DeleteFile(provider *Provider, objectKey string) error {
// check fullFilePath is there security issue
if strings.Contains(objectKey, "..") {
return fmt.Errorf("the objectKey: %s is not allowed", objectKey)
}
endpoint := getProviderEndpoint(provider)
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
if storageProvider == nil {

View File

@ -20,7 +20,7 @@ import (
"net/http"
"strings"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/authz"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package routers
import (
"fmt"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -18,7 +18,7 @@ import (
"fmt"
"strings"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -17,7 +17,7 @@ package routers
import (
"net/http"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/object"
)

View File

@ -17,7 +17,7 @@ package routers
import (
"fmt"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)

View File

@ -20,7 +20,7 @@
package routers
import (
"github.com/astaxie/beego"
"github.com/beego/beego"
"github.com/casdoor/casdoor/controllers"
)

View File

@ -19,7 +19,7 @@ import (
"os"
"strings"
"github.com/astaxie/beego/context"
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
)

View File

@ -19,8 +19,8 @@ import (
"net/http"
"strings"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/logs"
"github.com/beego/beego/context"
"github.com/beego/beego/logs"
)
func GetIPInfo(clientIP string) string {

View File

@ -17,7 +17,7 @@ package util
import (
"fmt"
"github.com/astaxie/beego/logs"
"github.com/beego/beego/logs"
)
func SafeGoroutine(fn func()) {

View File

@ -43,7 +43,7 @@ module.exports = {
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: {"@primary-color": "rgb(45,120,213)"},
modifyVars: {"@primary-color": "rgb(89,54,213)", "@border-radius-base": "5px"},
javascriptEnabled: true,
},
},

View File

@ -610,7 +610,7 @@ class App extends Component {
// theme="dark"
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
selectedKeys={[`${this.state.selectedMenuKey}`]}
style={{lineHeight: "64px", width: "80%", position: "absolute", left: "145px"}}
style={{lineHeight: "64px", width: "78%", position: "absolute", left: "145px"}}
>
{
this.renderMenu()
@ -682,7 +682,7 @@ class App extends Component {
textAlign: "center",
}
}>
Made with <span style={{color: "rgb(255, 255, 255)"}}></span> by <a style={{fontWeight: "bold", color: "black"}} target="_blank" href="https://casdoor.org" rel="noreferrer">Casdoor</a>
Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style={{paddingBottom: "3px"}} height={"20px"} alt={"Casdoor"} src={`${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`} /></a>
</Footer>
</>
);

View File

@ -28,7 +28,7 @@
color: #61dafb;
}
#root{
#root {
height: 100%;
}
@ -59,11 +59,18 @@
height: 70px; /* Footer height */
}
#language-box-corner {
position: absolute;
top: 75px;
right: 0;
}
.language_box {
background: url("@{StaticBaseUrl}/img/muti_language.svg");
background-size: 25px, 25px;
background-position: center;
background-repeat: no-repeat;
border-radius: 5px;
width: 45px;
height: 65px;
float: right;
@ -87,9 +94,19 @@
align-items: stretch;
}
.login-content{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
box-sizing: border-box;
margin: 0 auto;
position: relative;
}
.loginBackground {
height: 100%;
background: #ffffff no-repeat;
background: #fff no-repeat;
background-size: 100% 100%;
background-attachment: fixed;
}

View File

@ -37,8 +37,8 @@ class SelectLanguageBox extends React.Component {
Setting.changeLanguage(e.key);
}}>
<Menu.Item key="en" icon={flagIcon("US", "English")}>English</Menu.Item>
<Menu.Item key="es" icon={flagIcon("ES", "Español")}>Español</Menu.Item>
<Menu.Item key="zh" icon={flagIcon("CN", "简体中文")}>简体中文</Menu.Item>
<Menu.Item key="es" icon={flagIcon("ES", "Español")}>Español</Menu.Item>
<Menu.Item key="fr" icon={flagIcon("FR", "Français")}>Français</Menu.Item>
<Menu.Item key="de" icon={flagIcon("DE", "Deutsch")}>Deutsch</Menu.Item>
<Menu.Item key="ja" icon={flagIcon("JP", "日本語")}>日本語</Menu.Item>
@ -49,7 +49,7 @@ class SelectLanguageBox extends React.Component {
return (
<Dropdown overlay={menu} >
<div className="language_box" />
<div className="language_box" id={this.props.id} style={this.props.style} />
</Dropdown>
);
}

View File

@ -127,8 +127,12 @@ class UserEditPage extends React.Component {
this.getUser();
}
isSelf() {
return (this.state.user.id === this.props.account?.id);
}
isSelfOrAdmin() {
return (this.state.user.id === this.props.account?.id) || Setting.isAdminUser(this.props.account);
return this.isSelf() || Setting.isAdminUser(this.props.account);
}
renderAccountItem(accountItem) {
@ -136,7 +140,6 @@ class UserEditPage extends React.Component {
return null;
}
const isSelf = this.state.user.id === this.props.account?.id;
const isAdmin = Setting.isAdminUser(this.props.account);
// return (
@ -148,7 +151,7 @@ class UserEditPage extends React.Component {
// )
if (accountItem.viewRule === "Self") {
if (!isSelf && !isAdmin) {
if (!this.isSelfOrAdmin()) {
return null;
}
} else if (accountItem.viewRule === "Admin") {
@ -159,7 +162,7 @@ class UserEditPage extends React.Component {
let disabled = false;
if (accountItem.modifyRule === "Self") {
if (!isSelf && !isAdmin) {
if (!this.isSelfOrAdmin()) {
disabled = true;
}
} else if (accountItem.modifyRule === "Admin") {
@ -296,7 +299,11 @@ class UserEditPage extends React.Component {
}} />
</Col>
<Col span={11} >
{this.state.user.id === this.props.account?.id ? (<ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Email...")} destType={"email"} />) : null}
{
!this.isSelf() ? null : (
<ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Email...")} destType={"email"} />
)
}
</Col>
</Row>
);
@ -556,7 +563,7 @@ class UserEditPage extends React.Component {
{Setting.getLabel(i18next.t("user:WebAuthn credentials"), i18next.t("user:WebAuthn credentials"))} :
</Col>
<Col span={22} >
<WebAuthnCredentialTable table={this.state.user.webauthnCredentials} updateTable={(table) => {this.updateUserField("webauthnCredentials", table);}} refresh={this.getUser.bind(this)} />
<WebAuthnCredentialTable isSelf={this.isSelf()} table={this.state.user.webauthnCredentials} updateTable={(table) => {this.updateUserField("webauthnCredentials", table);}} refresh={this.getUser.bind(this)} />
</Col>
</Row>
);

View File

@ -19,40 +19,6 @@ import * as UserWebauthnBackend from "./backend/UserWebauthnBackend";
import * as Setting from "./Setting";
class WebAuthnCredentialTable extends React.Component {
render() {
const columns = [
{
title: i18next.t("user:WebAuthn credentials"),
dataIndex: "ID",
key: "ID",
},
{
title: i18next.t("general:Action"),
key: "action",
render: (text, record, index) => {
return (
<Button style={{marginTop: "5px", marginBottom: "5px", marginRight: "5px"}} type="danger" onClick={() => {this.deleteRow(this.props.table, index);}}>
{i18next.t("general:Delete")}
</Button>
);
},
},
];
return (
<Table scroll={{x: "max-content"}} rowKey={"ID"} columns={columns} dataSource={this.props.table} size="middle" bordered pagination={false}
title={() => (
<div>
{i18next.t("user:WebAuthn credentials")}&nbsp;&nbsp;&nbsp;&nbsp;
<Button style={{marginRight: "5px"}} type="primary" size="small" onClick={() => {this.registerWebAuthn();}}>
{i18next.t("general:Add")}
</Button>
</div>
)}
/>
);
}
deleteRow(table, i) {
table = Setting.deleteRow(table, i);
this.props.updateTable(table);
@ -71,6 +37,41 @@ class WebAuthnCredentialTable extends React.Component {
Setting.showMessage("error", `Failed to connect to server: ${error}`);
});
}
render() {
const columns = [
{
title: i18next.t("general:Name"),
dataIndex: "ID",
key: "ID",
},
{
title: i18next.t("general:Action"),
key: "action",
width: "170px",
render: (text, record, index) => {
return (
<Button style={{marginTop: "5px", marginBottom: "5px", marginRight: "5px"}} type="danger" onClick={() => {this.deleteRow(this.props.table, index);}}>
{i18next.t("general:Delete")}
</Button>
);
},
},
];
return (
<Table rowKey={"ID"} columns={columns} dataSource={this.props.table} size="middle" bordered pagination={false}
title={() => (
<div>
{i18next.t("user:WebAuthn credentials")}&nbsp;&nbsp;&nbsp;&nbsp;
<Button disabled={!this.props.isSelf} style={{marginRight: "5px"}} type="primary" size="small" onClick={() => {this.registerWebAuthn();}}>
{i18next.t("general:Add")}
</Button>
</div>
)}
/>
);
}
}
export default WebAuthnCredentialTable;

View File

@ -37,7 +37,7 @@ export function getEmailAndPhone(values) {
}).then((res) => res.json());
}
function oAuthParamsToQuery(oAuthParams) {
export function oAuthParamsToQuery(oAuthParams) {
// login
if (oAuthParams === null) {
return "";

View File

@ -28,6 +28,7 @@ import SelfLoginButton from "./SelfLoginButton";
import i18next from "i18next";
import CustomGithubCorner from "../CustomGithubCorner";
import {CountDownInput} from "../common/CountDownInput";
import SelectLanguageBox from "../SelectLanguageBox";
const {TabPane} = Tabs;
@ -41,7 +42,6 @@ class LoginPage extends React.Component {
owner: props.owner !== undefined ? props.owner : (props.match === undefined ? null : props.match.params.owner),
application: null,
mode: props.mode !== undefined ? props.mode : (props.match === undefined ? null : props.match.params.mode), // "signup" or "signin"
isCodeSignin: false,
msg: null,
username: null,
validEmailOrPhone: false,
@ -269,23 +269,6 @@ class LoginPage extends React.Component {
}
}
getSamlUrl(provider) {
const params = new URLSearchParams(this.props.location.search);
const clientId = params.get("client_id");
const application = params.get("state");
const realRedirectUri = params.get("redirect_uri");
const redirectUri = `${window.location.origin}/callback/saml`;
const providerName = provider.name;
const relayState = `${clientId}&${application}&${providerName}&${realRedirectUri}&${redirectUri}`;
AuthBackend.getSamlLogin(`${provider.owner}/${providerName}`, btoa(relayState)).then((res) => {
if (res.data2 === "POST") {
document.write(res.data);
} else {
window.location.href = res.data;
}
});
}
isProviderVisible(providerItem) {
if (this.state.mode === "signup") {
return Setting.isProviderVisibleForSignUp(providerItem);
@ -366,7 +349,7 @@ class LoginPage extends React.Component {
},
{
validator: (_, value) => {
if (this.state.isCodeSignin) {
if (this.state.loginMethod === "verificationCode") {
if (this.state.email !== "" && !Setting.isValidEmail(this.state.username) && !Setting.isValidPhone(this.state.username)) {
this.setState({validEmailOrPhone: false});
return Promise.reject(i18next.t("login:The input is not valid Email or Phone!"));
@ -389,7 +372,7 @@ class LoginPage extends React.Component {
<Input
id = "input"
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder={this.state.isCodeSignin ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
placeholder={(this.state.loginMethod === "verificationCode") ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
disabled={!application.enablePassword}
onChange={e => {
this.setState({
@ -416,29 +399,17 @@ class LoginPage extends React.Component {
</a>
</Form.Item>
<Form.Item>
{
this.state.loginMethod === "password" ?
(
<Button
type="primary"
htmlType="submit"
style={{width: "100%", marginBottom: "5px"}}
disabled={!application.enablePassword}
>
{i18next.t("login:Sign In")}
</Button>
) :
(
<Button
type="primary"
htmlType="submit"
style={{width: "100%", marginBottom: "5px"}}
disabled={!application.enablePassword}
>
{i18next.t("login:Sign in with WebAuthn")}
</Button>
)
}
<Button
type="primary"
htmlType="submit"
style={{width: "100%", marginBottom: "5px"}}
disabled={!application.enablePassword}
>
{
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
i18next.t("login:Sign In")
}
</Button>
{
this.renderFooter(application)
}
@ -446,7 +417,7 @@ class LoginPage extends React.Component {
<Form.Item>
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small");
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small", this.props.location);
})
}
</Form.Item>
@ -467,7 +438,7 @@ class LoginPage extends React.Component {
<br />
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
return ProviderButton.renderProviderLogo(providerItem.provider, application, 40, 10, "big");
return ProviderButton.renderProviderLogo(providerItem.provider, application, 40, 10, "big", this.props.location);
})
}
<div>
@ -496,19 +467,6 @@ class LoginPage extends React.Component {
} else {
return (
<React.Fragment>
<span style={{float: "left"}}>
{
!application.enableCodeSignin ? null : (
<a onClick={() => {
this.setState({
isCodeSignin: !this.state.isCodeSignin,
});
}}>
{this.state.isCodeSignin ? i18next.t("login:Sign in with password") : i18next.t("login:Sign in with code")}
</a>
)
}
</span>
<span style={{float: "right"}}>
{
!application.enableSignUp ? null : (
@ -529,14 +487,19 @@ class LoginPage extends React.Component {
}
}
sendSilentSigninData(data) {
if (Setting.inIframe()) {
const message = {tag: "Casdoor", type: "SilentSignin", data: data};
window.parent.postMessage(message, "*");
}
}
renderSignedInBox() {
if (this.props.account === undefined || this.props.account === null) {
if (window !== window.parent) {
const message = {tag: "Casdoor", type: "SilentSignin", data: "user-not-logged-in"};
window.parent.postMessage(message, "*");
}
this.sendSilentSigninData("user-not-logged-in");
return null;
}
const application = this.getApplicationObj();
if (this.props.account.owner !== application.organization) {
return null;
@ -545,10 +508,7 @@ class LoginPage extends React.Component {
const params = new URLSearchParams(this.props.location.search);
const silentSignin = params.get("silentSignin");
if (silentSignin !== null) {
if (window !== window.parent) {
const message = {tag: "Casdoor", type: "SilentSignin", data: "signing-in"};
window.parent.postMessage(message, "*");
}
this.sendSilentSigninData("signing-in");
const values = {};
values["application"] = this.state.application.name;
@ -614,7 +574,7 @@ class LoginPage extends React.Component {
const rawId = assertion.rawId;
const sig = assertion.response.signature;
const userHandle = assertion.response.userHandle;
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/finish`, {
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/finish${AuthBackend.oAuthParamsToQuery(oAuthParams)}`, {
method: "POST",
credentials: "include",
body: JSON.stringify({
@ -654,7 +614,23 @@ class LoginPage extends React.Component {
renderPasswordOrCodeInput() {
const application = this.getApplicationObj();
if (this.state.loginMethod === "password") {
return this.state.isCodeSignin ? (
return (
<Col span={24}>
<Form.Item
name="password"
rules={[{required: true, message: i18next.t("login:Please input your password!")}]}
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder={i18next.t("login:Password")}
disabled={!application.enablePassword}
/>
</Form.Item>
</Col>
);
} else if (this.state.loginMethod === "verificationCode") {
return (
<Col span={24}>
<Form.Item
name="code"
@ -667,32 +643,29 @@ class LoginPage extends React.Component {
/>
</Form.Item>
</Col>
) : (
<Col span={24}>
<Form.Item
name="password"
rules={[{required: true, message: i18next.t("login:Please input your password!")}]}
>
<Input
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder={i18next.t("login:Password")}
disabled={!application.enablePassword}
/>
</Form.Item>
</Col>
);
} else {
return null;
}
}
renderMethodChoiceBox() {
const application = this.getApplicationObj();
if (application.enableWebAuthn) {
if (application.enableCodeSignin || application.enableWebAuthn) {
return (
<div>
<Tabs defaultActiveKey="password" onChange={(key) => {this.setState({loginMethod: key});}} centered>
<Tabs size={"small"} defaultActiveKey="password" onChange={(key) => {this.setState({loginMethod: key});}} centered>
<TabPane tab={i18next.t("login:Password")} key="password" />
<TabPane tab={"WebAuthn"} key="webAuthn" />
{
!application.enableCodeSignin ? null : (
<TabPane tab={i18next.t("login:Verification Code")} key="verificationCode" />
)
}
{
!application.enableWebAuthn ? null : (
<TabPane tab={i18next.t("login:WebAuthn")} key="webAuthn" />
)
}
</Tabs>
</div>
);
@ -726,27 +699,29 @@ class LoginPage extends React.Component {
return (
<div className="loginBackground" style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${application.formBackgroundUrl})`}}>
<CustomGithubCorner />
<Row >
<Row>
<Col span={8} offset={application.formOffset === 0 || Setting.inIframe() || Setting.isMobile() ? 8 : application.formOffset} style={{display: "flex", justifyContent: "center"}}>
<div style={{marginTop: "80px", marginBottom: "50px", textAlign: "center", ...formStyle}}>
<div>
{
Setting.renderHelmet(application)
}
{
Setting.renderLogo(application)
}
{/* {*/}
{/* this.state.clientId !== null ? "Redirect" : null*/}
{/* }*/}
{
this.renderSignedInBox()
}
{
this.renderForm(application)
}
<div className="login-content">
<div style={{marginTop: "80px", marginBottom: "50px", textAlign: "center", ...formStyle}}>
<SelectLanguageBox id="language-box-corner" style={{top: "80px", right: "5px"}} />
<div>
{
Setting.renderHelmet(application)
}
{
Setting.renderLogo(application)
}
{/* {*/}
{/* this.state.clientId !== null ? "Redirect" : null*/}
{/* }*/}
{
this.renderSignedInBox()
}
{
this.renderForm(application)
}
</div>
</div>
</div>
</Col>
</Row>

View File

@ -39,6 +39,7 @@ import SteamLoginButton from "./SteamLoginButton";
import BilibiliLoginButton from "./BilibiliLoginButton";
import OktaLoginButton from "./OktaLoginButton";
import DouyinLoginButton from "./DouyinLoginButton";
import * as AuthBackend from "./AuthBackend";
function getSigninButton(type) {
const text = i18next.t("login:Sign in with {type}").replace("{type}", type);
@ -95,7 +96,24 @@ function getSigninButton(type) {
return text;
}
export function renderProviderLogo(provider, application, width, margin, size) {
function getSamlUrl(provider, location) {
const params = new URLSearchParams(location.search);
const clientId = params.get("client_id");
const application = params.get("state");
const realRedirectUri = params.get("redirect_uri");
const redirectUri = `${window.location.origin}/callback/saml`;
const providerName = provider.name;
const relayState = `${clientId}&${application}&${providerName}&${realRedirectUri}&${redirectUri}`;
AuthBackend.getSamlLogin(`${provider.owner}/${providerName}`, btoa(relayState)).then((res) => {
if (res.data2 === "POST") {
document.write(res.data);
} else {
window.location.href = res.data;
}
});
}
export function renderProviderLogo(provider, application, width, margin, size, location) {
if (size === "small") {
if (provider.category === "OAuth") {
return (
@ -105,7 +123,7 @@ export function renderProviderLogo(provider, application, width, margin, size) {
);
} else if (provider.category === "SAML") {
return (
<a key={provider.displayName} onClick={this.getSamlUrl.bind(this, provider)}>
<a key={provider.displayName} onClick={() => getSamlUrl(provider, location)}>
<img width={width} height={width} src={getProviderLogoURL(provider)} alt={provider.displayName} style={{margin: margin}} />
</a>
);

View File

@ -51,7 +51,7 @@ class SamlCallback extends React.Component {
const samlResponse = params.get("samlResponse");
const messages = atob(relayState).split("&");
const clientId = messages[0];
const applicationName = messages[1] === "null" ? "app-built-in" : messages[1];
const applicationName = (messages[1] === "null" || messages[1] === "undefined") ? "app-built-in" : messages[1];
const providerName = messages[2];
const redirectUri = messages[3];
const responseType = this.getResponseType(redirectUri);

View File

@ -25,6 +25,7 @@ import * as ApplicationBackend from "../backend/ApplicationBackend";
import {CountDownInput} from "../common/CountDownInput";
import SelectRegionBox from "../SelectRegionBox";
import CustomGithubCorner from "../CustomGithubCorner";
import SelectLanguageBox from "../SelectLanguageBox";
const formItemLayout = {
labelCol: {
@ -595,7 +596,7 @@ class SignupPage extends React.Component {
</Form.Item>
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small");
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small", this.props.location);
})
}
</Form>
@ -622,16 +623,19 @@ class SignupPage extends React.Component {
&nbsp;
<Row>
<Col span={8} offset={application.formOffset === 0 || Setting.inIframe() || Setting.isMobile() ? 8 : application.formOffset} style={{display: "flex", justifyContent: "center"}} >
<div style={{marginBottom: "10px", textAlign: "center", ...formStyle}}>
{
Setting.renderHelmet(application)
}
{
Setting.renderLogo(application)
}
{
this.renderForm(application)
}
<div className="login-content">
<div style={{marginBottom: "10px", textAlign: "center", ...formStyle}}>
<SelectLanguageBox id="language-box-corner" style={{top: "3px", right: "5px"}} />
{
Setting.renderHelmet(application)
}
{
Setting.renderLogo(application)
}
{
this.renderForm(application)
}
</div>
</div>
</Col>
</Row>

View File

@ -87,7 +87,7 @@ export const CaptchaPreview = ({
backgroundRepeat: "no-repeat",
height: "80px",
width: "200px",
borderRadius: "3px",
borderRadius: "5px",
border: "1px solid #ccc",
marginBottom: 10,
}}

View File

@ -101,7 +101,7 @@ export const CountDownInput = (props) => {
backgroundRepeat: "no-repeat",
height: "80px",
width: "200px",
borderRadius: "3px",
borderRadius: "5px",
border: "1px solid #ccc",
marginBottom: 10,
}}

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "Bitte geben Sie Ihren Benutzernamen, E-Mail oder Telefon ein!",
"Sign In": "Anmelden",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "Mit Code anmelden",
"Sign in with password": "Mit Passwort anmelden",
"Sign in with {type}": "Mit {type} anmelden",
"Signing in...": "Anmelden...",
"The input is not valid Email or Phone!": "Die Eingabe ist keine gültige E-Mail oder Telefon!",
"To access": "Zu Zugriff",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "jetzt anmelden",
"username, Email or phone": "Benutzername, E-Mail oder Telefon"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
"Sign In": "Sign In",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "Sign in with code",
"Sign in with password": "Sign in with password",
"Sign in with {type}": "Sign in with {type}",
"Signing in...": "Signing in...",
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!",
"To access": "To access",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "sign up now",
"username, Email or phone": "username, Email or phone"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "Veuillez entrer votre nom d'utilisateur, votre e-mail ou votre téléphone!",
"Sign In": "Se connecter",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "Se connecter avec le code",
"Sign in with password": "Se connecter avec le mot de passe",
"Sign in with {type}": "Se connecter avec {type}",
"Signing in...": "Connexion en cours...",
"The input is not valid Email or Phone!": "L'entrée n'est pas valide Email ou Téléphone !",
"To access": "Pour accéder à",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "inscrivez-vous maintenant",
"username, Email or phone": "nom d'utilisateur, e-mail ou téléphone"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "ユーザー名、メールアドレスまたは電話番号を入力してください。",
"Sign In": "サインイン",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "コードでサインイン",
"Sign in with password": "パスワードでサインイン",
"Sign in with {type}": "{type} でサインイン",
"Signing in...": "サインイン中...",
"The input is not valid Email or Phone!": "入力されたメールアドレスまたは電話番号が正しくありません。",
"To access": "アクセスするには",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "今すぐサインアップ",
"username, Email or phone": "ユーザー名、メールアドレスまたは電話番号"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
"Sign In": "Sign In",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "Sign in with code",
"Sign in with password": "Sign in with password",
"Sign in with {type}": "Sign in with {type}",
"Signing in...": "Signing in...",
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!",
"To access": "To access",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "sign up now",
"username, Email or phone": "username, Email or phone"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "Пожалуйста, введите ваше имя пользователя, адрес электронной почты или телефон!",
"Sign In": "Войти",
"Sign in with WebAuthn": "Sign in with WebAuthn",
"Sign in with code": "Войти с помощью кода",
"Sign in with password": "Войти с помощью пароля",
"Sign in with {type}": "Войти с помощью {type}",
"Signing in...": "Вход...",
"The input is not valid Email or Phone!": "Введен неверный адрес электронной почты или телефон!",
"To access": "На доступ",
"Verification Code": "Verification Code",
"WebAuthn": "WebAuthn",
"sign up now": "зарегистрироваться",
"username, Email or phone": "имя пользователя, адрес электронной почты или телефон"
},

View File

@ -277,12 +277,12 @@
"Please input your username, Email or phone!": "请输入您的用户名、Email或手机号",
"Sign In": "登录",
"Sign in with WebAuthn": "WebAuthn登录",
"Sign in with code": "验证码登录",
"Sign in with password": "密码登录",
"Sign in with {type}": "{type}登录",
"Signing in...": "正在登录...",
"The input is not valid Email or Phone!": "您输入的电子邮箱格式或手机号有误!",
"To access": "访问",
"Verification Code": "验证码",
"WebAuthn": "Web身份验证",
"sign up now": "立即注册",
"username, Email or phone": "用户名、Email或手机号"
},
@ -702,7 +702,7 @@
"Unlink": "解绑",
"Upload (.xlsx)": "上传(.xlsx",
"Upload a photo": "上传头像",
"WebAuthn credentials": "WebAuthn credentials",
"WebAuthn credentials": "WebAuthn凭据",
"input password": "输入密码"
},
"webhook": {