mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-27 16:30:46 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
efacf8226c | ||
![]() |
6beb68dcce | ||
![]() |
c9b990a319 | ||
![]() |
eedcde3aa5 | ||
![]() |
950a274b23 | ||
![]() |
478bd05db4 | ||
![]() |
9256791420 | ||
![]() |
6f2ef32d02 | ||
![]() |
8b8c866fd2 | ||
![]() |
6f7230e949 | ||
![]() |
9558bb4167 |
@@ -20,9 +20,9 @@ import (
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
stringadapter "github.com/qiangmzsx/string-adapter/v2"
|
||||
)
|
||||
|
||||
|
@@ -254,7 +254,10 @@ func (c *ApiController) Logout() {
|
||||
|
||||
if accessToken == "" && redirectUri == "" {
|
||||
c.ClearUserSession()
|
||||
object.DeleteSessionId(user, c.Ctx.Input.CruSession.SessionID())
|
||||
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
||||
owner, username := util.GetOwnerAndNameFromId(user)
|
||||
|
||||
object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
|
||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||
|
||||
application := c.GetSessionApplication()
|
||||
@@ -291,7 +294,8 @@ func (c *ApiController) Logout() {
|
||||
}
|
||||
|
||||
c.ClearUserSession()
|
||||
object.DeleteSessionId(user, c.Ctx.Input.CruSession.SessionID())
|
||||
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
||||
object.DeleteSessionId(util.GetSessionId(object.CasdoorOrganization, object.CasdoorApplication, user), c.Ctx.Input.CruSession.SessionID())
|
||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||
|
||||
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
|
||||
|
@@ -139,8 +139,13 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
})
|
||||
}
|
||||
|
||||
if resp.Status == "ok" {
|
||||
object.SetSession(user.GetId(), c.Ctx.Input.CruSession.SessionID())
|
||||
if resp.Status == "ok" && user.Owner == object.CasdoorOrganization && application.Name == object.CasdoorApplication {
|
||||
object.AddSession(&object.Session{
|
||||
Owner: user.Owner,
|
||||
Name: user.Name,
|
||||
Application: application.Name,
|
||||
SessionId: []string{c.Ctx.Input.CruSession.SessionID()},
|
||||
})
|
||||
}
|
||||
|
||||
return resp
|
||||
|
@@ -18,9 +18,9 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
func (c *ApiController) GetCasbinAdapters() {
|
||||
|
@@ -180,6 +180,7 @@ func (c *ApiController) UploadResource() {
|
||||
fileType, _ = util.GetOwnerAndNameFromId(mimeType)
|
||||
}
|
||||
|
||||
fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175)
|
||||
if tag != "avatar" && tag != "termsOfUse" {
|
||||
ext := filepath.Ext(filepath.Base(fullFilePath))
|
||||
index := len(fullFilePath) - len(ext)
|
||||
|
@@ -22,29 +22,10 @@ import (
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// DeleteSession
|
||||
// @Title DeleteSession
|
||||
// @Tag Session API
|
||||
// @Description Delete session by userId
|
||||
// @Param id query string true "The id ( owner/name )(owner/name) of user."
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /delete-session [post]
|
||||
func (c *ApiController) DeleteSession() {
|
||||
var session object.Session
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteSession(util.GetId(session.Owner, session.Name)))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetSessions
|
||||
// @Title GetSessions
|
||||
// @Tag Session API
|
||||
// @Description Get organization user sessions
|
||||
// @Description Get organization user sessions.
|
||||
// @Param owner query string true "The organization name"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /get-sessions [get]
|
||||
@@ -66,3 +47,93 @@ func (c *ApiController) GetSessions() {
|
||||
c.ResponseOk(sessions, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetSingleSession
|
||||
// @Title GetSingleSession
|
||||
// @Tag Session API
|
||||
// @Description Get session for one user in one application.
|
||||
// @Param id query string true "The id(organization/application/user) of session"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /get-session [get]
|
||||
func (c *ApiController) GetSingleSession() {
|
||||
id := c.Input().Get("sessionPkId")
|
||||
|
||||
c.Data["json"] = object.GetSingleSession(id)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateSession
|
||||
// @Title UpdateSession
|
||||
// @Tag Session API
|
||||
// @Description Update session for one user in one application.
|
||||
// @Param id query string true "The id(organization/application/user) of session"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /update-session [post]
|
||||
func (c *ApiController) UpdateSession() {
|
||||
var session object.Session
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateSession(util.GetSessionId(session.Owner, session.Name, session.Application), &session))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddSession
|
||||
// @Title AddSession
|
||||
// @Tag Session API
|
||||
// @Description Add session for one user in one application. If there are other existing sessions, join the session into the list.
|
||||
// @Param id query string true "The id(organization/application/user) of session"
|
||||
// @Param sessionId query string true "sessionId to be added"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /add-session [post]
|
||||
func (c *ApiController) AddSession() {
|
||||
var session object.Session
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddSession(&session))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteSession
|
||||
// @Title DeleteSession
|
||||
// @Tag Session API
|
||||
// @Description Delete session for one user in one application.
|
||||
// @Param id query string true "The id(organization/application/user) of session"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /delete-session [post]
|
||||
func (c *ApiController) DeleteSession() {
|
||||
var session object.Session
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteSession(util.GetSessionId(session.Owner, session.Name, session.Application)))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// IsSessionDuplicated
|
||||
// @Title IsSessionDuplicated
|
||||
// @Tag Session API
|
||||
// @Description Check if there are other different sessions for one user in one application.
|
||||
// @Param id query string true "The id(organization/application/user) of session"
|
||||
// @Param sessionId query string true "sessionId to be checked"
|
||||
// @Success 200 {array} string The Response object
|
||||
// @router /is-session-duplicated [get]
|
||||
func (c *ApiController) IsSessionDuplicated() {
|
||||
id := c.Input().Get("sessionPkId")
|
||||
sessionId := c.Input().Get("sessionId")
|
||||
|
||||
isUserSessionDuplicated := object.IsSessionDuplicated(id, sessionId)
|
||||
c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated}
|
||||
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@@ -172,6 +172,7 @@ func (c *ApiController) GetOAuthCode() {
|
||||
// @router /login/oauth/access_token [post]
|
||||
func (c *ApiController) GetOAuthToken() {
|
||||
grantType := c.Input().Get("grant_type")
|
||||
refreshToken := c.Input().Get("refresh_token")
|
||||
clientId := c.Input().Get("client_id")
|
||||
clientSecret := c.Input().Get("client_secret")
|
||||
code := c.Input().Get("code")
|
||||
@@ -192,6 +193,7 @@ func (c *ApiController) GetOAuthToken() {
|
||||
clientId = tokenRequest.ClientId
|
||||
clientSecret = tokenRequest.ClientSecret
|
||||
grantType = tokenRequest.GrantType
|
||||
refreshToken = tokenRequest.RefreshToken
|
||||
code = tokenRequest.Code
|
||||
verifier = tokenRequest.Verifier
|
||||
scope = tokenRequest.Scope
|
||||
@@ -203,7 +205,7 @@ func (c *ApiController) GetOAuthToken() {
|
||||
}
|
||||
host := c.Ctx.Request.Host
|
||||
|
||||
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, tag, avatar, c.GetAcceptLanguage())
|
||||
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
||||
c.SetTokenErrorHttpStatus()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
11
go.mod
11
go.mod
@@ -9,14 +9,14 @@ require (
|
||||
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
|
||||
github.com/casdoor/go-sms-sender v0.5.1
|
||||
github.com/casdoor/gomail/v2 v2.0.1
|
||||
github.com/casdoor/oss v1.2.0
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
github.com/denisenkom/go-mssqldb v0.9.0
|
||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b
|
||||
github.com/forestmgy/ldapserver v1.1.0
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
|
||||
github.com/go-ldap/ldap/v3 v3.3.0
|
||||
github.com/go-pay/gopay v1.5.72
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
@@ -41,18 +41,15 @@ require (
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/thanhpk/randstr v1.0.4
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/xorm-io/core v0.7.4
|
||||
github.com/xorm-io/xorm v1.1.6
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84
|
||||
xorm.io/builder v0.3.12 // indirect
|
||||
xorm.io/core v0.7.2
|
||||
xorm.io/xorm v1.1.2
|
||||
)
|
||||
|
31
go.sum
31
go.sum
@@ -58,7 +58,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b h1:EgJ6N2S0h1WfFIjU5/VVHWbMSVYXAluop97Qxpr/lfQ=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b/go.mod h1:3SAoF0F5EbcOuBD5WT9nYkbIJieBS84cUQXADbXeBsU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -73,7 +72,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1075 h1:Z0SzZttfYI/raZ5O9WF3cezZJTS
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1075/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
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/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=
|
||||
@@ -96,12 +94,14 @@ github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n
|
||||
github.com/casbin/casbin/v2 v2.28.3/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||
github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeKF0=
|
||||
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||
github.com/casbin/xorm-adapter/v3 v3.0.1 h1:0l0zkYxo6cNuIdrBZgFxlje1TRvmheYa/zIp+sGPK58=
|
||||
github.com/casbin/xorm-adapter/v3 v3.0.1/go.mod h1:1BL7rHEDXrxO+vQdSo/ZaWKRivXl7YTos67GdMYcd20=
|
||||
github.com/casdoor/go-sms-sender v0.5.1 h1:1/Wp1OLkVAVY4lEGQhekSNetSAWhnPcxYPV7xpCZgC0=
|
||||
github.com/casdoor/go-sms-sender v0.5.1/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
||||
github.com/casdoor/gomail/v2 v2.0.1 h1:J+FG6x80s9e5lBHUn8Sv0Y56mud34KiWih5YdmudR/w=
|
||||
github.com/casdoor/gomail/v2 v2.0.1/go.mod h1:VnGPslEAtpix5FjHisR/WKB1qvZDBaujbikxDe9d+2Q=
|
||||
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
||||
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4 h1:vB04Ao8n2jA7aFBI9F+gGXo9+Aa1IQP6mTdo50913DM=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4/go.mod h1:4WTcUw+bTgBylGHeGHzTtBvuTXRS23dtwzFLl9tsgFM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -126,7 +126,6 @@ github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWW
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
||||
@@ -154,8 +153,6 @@ github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df h1:Bao6dhmbTA1KFVxmJ6nBoMuOJit2yjEgLJpIMYpop0E=
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df/go.mod h1:GJr+FCSXshIwgHBtLglIg9M2l2kQSi6QjVAngtzI08Y=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ=
|
||||
@@ -270,6 +267,7 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
|
||||
github.com/jinzhu/configor v1.2.1 h1:OKk9dsR8i6HPOCZR8BcMtcEImAFjIhbJFZNyn5GCZko=
|
||||
github.com/jinzhu/configor v1.2.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc=
|
||||
@@ -337,7 +335,6 @@ github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
@@ -456,6 +453,12 @@ github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF
|
||||
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xorm-io/builder v0.3.13 h1:J4oZxt4Gjgm/Si9iKazfzYwHB/ijEOD9EHInyjOSX+M=
|
||||
github.com/xorm-io/builder v0.3.13/go.mod h1:24o5riRwzre2WvjmN+LM4YpUtJg7W8MdvJ8H57rvrJA=
|
||||
github.com/xorm-io/core v0.7.4 h1:qIznlqqmYNEb03ewzRXCrNkbbxpkgc/44nVF8yoFV7Y=
|
||||
github.com/xorm-io/core v0.7.4/go.mod h1:GueyhafDnkB0KK0fXX/dEhr/P1EAGW0GLmoNDUEE1Mo=
|
||||
github.com/xorm-io/xorm v1.1.6 h1:s4fDpUXJx8Zr/PBovXNaadn+v1P3h/U3iV4OxAkWS8s=
|
||||
github.com/xorm-io/xorm v1.1.6/go.mod h1:7nsSUdmgLIcqHSSaKOzbVQiZtzIzbpGf1GGSYp6DD70=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -520,7 +523,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -789,8 +791,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
@@ -847,12 +847,3 @@ modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
||||
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
||||
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
xorm.io/xorm v1.1.2 h1:bje+1KZvK3m5AHtZNfUDlKEEyuw/IRHT+an0CLIG5TU=
|
||||
xorm.io/xorm v1.1.2/go.mod h1:Cb0DKYTHbyECMaSfgRnIZp5aiUgQozxcJJ0vzcLGJSg=
|
||||
|
5
main.go
5
main.go
@@ -35,7 +35,10 @@ func main() {
|
||||
createDatabase := flag.Bool("createDatabase", false, "true if you need Casdoor to create database")
|
||||
flag.Parse()
|
||||
|
||||
object.InitAdapter(*createDatabase)
|
||||
object.InitAdapter()
|
||||
object.DoMigration()
|
||||
object.CreateTables(*createDatabase)
|
||||
|
||||
object.InitDb()
|
||||
object.InitFromFile()
|
||||
object.InitDefaultStorageProvider()
|
||||
|
@@ -19,15 +19,15 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/beego/beego"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
_ "github.com/denisenkom/go-mssqldb" // db = mssql
|
||||
_ "github.com/go-sql-driver/mysql" // db = mysql
|
||||
_ "github.com/lib/pq" // db = postgres
|
||||
_ "modernc.org/sqlite" // db = sqlite
|
||||
"xorm.io/core"
|
||||
"xorm.io/xorm"
|
||||
"github.com/xorm-io/core"
|
||||
"github.com/xorm-io/xorm"
|
||||
_ "modernc.org/sqlite" // db = sqlite
|
||||
)
|
||||
|
||||
var adapter *Adapter
|
||||
@@ -40,12 +40,16 @@ func InitConfig() {
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
InitAdapter(true)
|
||||
MigrateDatabase()
|
||||
InitAdapter()
|
||||
DoMigration()
|
||||
CreateTables(true)
|
||||
}
|
||||
|
||||
func InitAdapter(createDatabase bool) {
|
||||
func InitAdapter() {
|
||||
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
}
|
||||
|
||||
func CreateTables(createDatabase bool) {
|
||||
if createDatabase {
|
||||
adapter.CreateDatabase()
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
"github.com/casdoor/casdoor/idp"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type SignupItem struct {
|
||||
|
@@ -20,9 +20,9 @@ import (
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type CasbinAdapter struct {
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
|
@@ -19,7 +19,7 @@ package object
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/go-gomail/gomail"
|
||||
"github.com/casdoor/gomail/v2"
|
||||
)
|
||||
|
||||
func getDialer(provider *Provider) *gomail.Dialer {
|
||||
@@ -45,6 +45,10 @@ func SendEmail(provider *Provider, title string, content string, dest string, se
|
||||
message.SetHeader("Subject", title)
|
||||
message.SetBody("text/html", content)
|
||||
|
||||
if provider.Type == "Mailtrap" {
|
||||
message.SkipUsernameCheck = true
|
||||
}
|
||||
|
||||
return dialer.DialAndSend(message)
|
||||
}
|
||||
|
||||
|
@@ -34,8 +34,6 @@ func InitDb() {
|
||||
initBuiltInApplication()
|
||||
initBuiltInCert()
|
||||
initBuiltInLdap()
|
||||
} else {
|
||||
MigrateDatabase()
|
||||
}
|
||||
|
||||
initWebAuthn()
|
||||
|
47
object/migrator.go
Normal file
47
object/migrator.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import "github.com/xorm-io/xorm/migrate"
|
||||
|
||||
type Migrator interface {
|
||||
IsMigrationNeeded() bool
|
||||
DoMigration() *migrate.Migration
|
||||
}
|
||||
|
||||
func DoMigration() {
|
||||
migrators := []Migrator{
|
||||
&Migrator_1_101_0_PR_1083{},
|
||||
&Migrator_1_235_0_PR_1530{},
|
||||
&Migrator_1_240_0_PR_1539{},
|
||||
// more migrators add here in chronological order...
|
||||
}
|
||||
|
||||
migrations := []*migrate.Migration{}
|
||||
|
||||
for _, migrator := range migrators {
|
||||
if migrator.IsMigrationNeeded() {
|
||||
migrations = append(migrations, migrator.DoMigration())
|
||||
}
|
||||
}
|
||||
|
||||
options := &migrate.Options{
|
||||
TableName: "migration",
|
||||
IDColumnName: "id",
|
||||
}
|
||||
|
||||
m := migrate.New(adapter.Engine, options, migrations)
|
||||
m.Migrate()
|
||||
}
|
@@ -10,51 +10,36 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.package object
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/migrate"
|
||||
"github.com/xorm-io/xorm"
|
||||
"github.com/xorm-io/xorm/migrate"
|
||||
)
|
||||
|
||||
func MigrateDatabase() {
|
||||
migrations := []*migrate.Migration{
|
||||
MigrateCasbinRule(),
|
||||
MigratePermissionRule(),
|
||||
}
|
||||
type Migrator_1_101_0_PR_1083 struct{}
|
||||
|
||||
m := migrate.New(adapter.Engine, migrate.DefaultOptions, migrations)
|
||||
m.Migrate()
|
||||
func (*Migrator_1_101_0_PR_1083) IsMigrationNeeded() bool {
|
||||
exist1, _ := adapter.Engine.IsTableExist("model")
|
||||
exist2, _ := adapter.Engine.IsTableExist("permission")
|
||||
exist3, _ := adapter.Engine.IsTableExist("permission_rule")
|
||||
|
||||
if exist1 && exist2 && exist3 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func MigrateCasbinRule() *migrate.Migration {
|
||||
migration := migrate.Migration{
|
||||
ID: "20221015CasbinRule--fill ptype field with p",
|
||||
Migrate: func(engine *xorm.Engine) error {
|
||||
_, err := engine.Cols("ptype").Update(&xormadapter.CasbinRule{
|
||||
Ptype: "p",
|
||||
})
|
||||
return err
|
||||
},
|
||||
Rollback: func(engine *xorm.Engine) error {
|
||||
return engine.DropTables(&xormadapter.CasbinRule{})
|
||||
},
|
||||
}
|
||||
|
||||
return &migration
|
||||
}
|
||||
|
||||
func MigratePermissionRule() *migrate.Migration {
|
||||
func (*Migrator_1_101_0_PR_1083) DoMigration() *migrate.Migration {
|
||||
migration := migrate.Migration{
|
||||
ID: "20230209MigratePermissionRule--Use V5 instead of V1 to store permissionID",
|
||||
Migrate: func(engine *xorm.Engine) error {
|
||||
models := []*Model{}
|
||||
err := engine.Find(&models, &Model{})
|
||||
err := engine.Table("model").Find(&models, &Model{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
49
object/migrator_1_235_0_PR_1530.go
Normal file
49
object/migrator_1_235_0_PR_1530.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
"github.com/xorm-io/xorm"
|
||||
"github.com/xorm-io/xorm/migrate"
|
||||
)
|
||||
|
||||
type Migrator_1_235_0_PR_1530 struct{}
|
||||
|
||||
func (*Migrator_1_235_0_PR_1530) IsMigrationNeeded() bool {
|
||||
exist, _ := adapter.Engine.IsTableExist("casbin_rule")
|
||||
|
||||
if exist {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (*Migrator_1_235_0_PR_1530) DoMigration() *migrate.Migration {
|
||||
migration := migrate.Migration{
|
||||
ID: "20221015CasbinRule--fill ptype field with p",
|
||||
Migrate: func(engine *xorm.Engine) error {
|
||||
_, err := engine.Cols("ptype").Update(&xormadapter.CasbinRule{
|
||||
Ptype: "p",
|
||||
})
|
||||
return err
|
||||
},
|
||||
Rollback: func(engine *xorm.Engine) error {
|
||||
return engine.DropTables(&xormadapter.CasbinRule{})
|
||||
},
|
||||
}
|
||||
|
||||
return &migration
|
||||
}
|
141
object/migrator_1_240_0_PR_1539.go
Normal file
141
object/migrator_1_240_0_PR_1539.go
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/xorm-io/xorm"
|
||||
"github.com/xorm-io/xorm/migrate"
|
||||
)
|
||||
|
||||
type Migrator_1_240_0_PR_1539 struct{}
|
||||
|
||||
func (*Migrator_1_240_0_PR_1539) IsMigrationNeeded() bool {
|
||||
exist, _ := adapter.Engine.IsTableExist("session")
|
||||
err := adapter.Engine.Table("session").Find(&[]*Session{})
|
||||
|
||||
if exist && err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (*Migrator_1_240_0_PR_1539) DoMigration() *migrate.Migration {
|
||||
migration := migrate.Migration{
|
||||
ID: "20230211MigrateSession--Create a new field 'application' for table `session`",
|
||||
Migrate: func(engine *xorm.Engine) error {
|
||||
if alreadyCreated, _ := engine.IsTableExist("session_tmp"); alreadyCreated {
|
||||
return errors.New("there is already a table called 'session_tmp', please rename or delete it for casdoor version migration and restart")
|
||||
}
|
||||
|
||||
type oldSession struct {
|
||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
|
||||
SessionId []string `json:"sessionId"`
|
||||
}
|
||||
|
||||
tx := engine.NewSession()
|
||||
|
||||
defer tx.Close()
|
||||
|
||||
err := tx.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Table("session_tmp").CreateTable(&Session{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldSessions := []*oldSession{}
|
||||
newSessions := []*Session{}
|
||||
|
||||
err = tx.Table("session").Find(&oldSessions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, oldSession := range oldSessions {
|
||||
newApplication := "null"
|
||||
if oldSession.Owner == "built-in" {
|
||||
newApplication = "app-built-in"
|
||||
}
|
||||
newSessions = append(newSessions, &Session{
|
||||
Owner: oldSession.Owner,
|
||||
Name: oldSession.Name,
|
||||
Application: newApplication,
|
||||
CreatedTime: oldSession.CreatedTime,
|
||||
SessionId: oldSession.SessionId,
|
||||
})
|
||||
}
|
||||
|
||||
rollbackFlag := false
|
||||
_, err = tx.Table("session_tmp").Insert(newSessions)
|
||||
count1, _ := tx.Table("session_tmp").Count()
|
||||
count2, _ := tx.Table("session").Count()
|
||||
|
||||
if err != nil || count1 != count2 {
|
||||
rollbackFlag = true
|
||||
}
|
||||
|
||||
delete := &Session{
|
||||
Application: "null",
|
||||
}
|
||||
_, err = tx.Table("session_tmp").Delete(*delete)
|
||||
if err != nil {
|
||||
rollbackFlag = true
|
||||
}
|
||||
|
||||
if rollbackFlag {
|
||||
tx.DropTable("session_tmp")
|
||||
return errors.New("there is something wrong with data migration for table `session`, if there is a table called `session_tmp` not created by you in casdoor, please drop it, then restart anyhow")
|
||||
}
|
||||
|
||||
err = tx.DropTable("session")
|
||||
if err != nil {
|
||||
return errors.New("fail to drop table `session` for casdoor, please drop it and rename the table `session_tmp` to `session` manually and restart")
|
||||
}
|
||||
|
||||
// Already drop table `session`
|
||||
// Can't find an api from xorm for altering table name
|
||||
err = tx.Table("session").CreateTable(&Session{})
|
||||
if err != nil {
|
||||
return errors.New("there is something wrong with data migration for table `session`, please restart")
|
||||
}
|
||||
|
||||
sessions := []*Session{}
|
||||
tx.Table("session_tmp").Find(&sessions)
|
||||
_, err = tx.Table("session").Insert(sessions)
|
||||
if err != nil {
|
||||
return errors.New("there is something wrong with data migration for table `session`, please drop table `session` and rename table `session_tmp` to `session` and restart")
|
||||
}
|
||||
|
||||
err = tx.DropTable("session_tmp")
|
||||
if err != nil {
|
||||
return errors.New("fail to drop table `session_tmp` for casdoor, please drop it manually and restart")
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return &migration
|
||||
}
|
@@ -19,7 +19,7 @@ import (
|
||||
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/casdoor/casdoor/cred"
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type AccountItem struct {
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Payment struct {
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Permission struct {
|
||||
|
@@ -21,8 +21,8 @@ import (
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/config"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
func getEnforcer(permission *Permission) *casbin.Enforcer {
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Product struct {
|
||||
|
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Provider struct {
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Resource struct {
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
|
@@ -15,84 +15,27 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
var (
|
||||
CasdoorApplication = "app-built-in"
|
||||
CasdoorOrganization = "built-in"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||
Application string `xorm:"varchar(100) notnull pk" json:"application"`
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
|
||||
SessionId []string `json:"sessionId"`
|
||||
}
|
||||
|
||||
func SetSession(id string, sessionId string) {
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
session := &Session{Owner: owner, Name: name}
|
||||
get, err := adapter.Engine.Get(session)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
session.SessionId = append(session.SessionId, sessionId)
|
||||
if get {
|
||||
_, err = adapter.Engine.ID(core.PK{owner, name}).Update(session)
|
||||
} else {
|
||||
session.CreatedTime = util.GetCurrentTime()
|
||||
_, err = adapter.Engine.Insert(session)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteSession(id string) bool {
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
|
||||
session := &Session{Owner: owner, Name: name}
|
||||
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
DeleteBeegoSession(session.SessionId)
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
|
||||
return affected != 0
|
||||
}
|
||||
|
||||
func DeleteSessionId(id string, sessionId string) bool {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
|
||||
session := &Session{Owner: owner, Name: name}
|
||||
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
DeleteBeegoSession([]string{sessionId})
|
||||
session.SessionId = util.DeleteVal(session.SessionId, sessionId)
|
||||
|
||||
if len(session.SessionId) < 1 {
|
||||
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
|
||||
return affected != 0
|
||||
} else {
|
||||
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Update(session)
|
||||
return affected != 0
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteBeegoSession(sessionIds []string) {
|
||||
for _, sessionId := range sessionIds {
|
||||
err := beego.GlobalSessions.GetProvider().SessionDestroy(sessionId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetSessions(owner string) []*Session {
|
||||
sessions := []*Session{}
|
||||
var err error
|
||||
@@ -128,3 +71,131 @@ func GetSessionCount(owner, field, value string) int {
|
||||
|
||||
return int(count)
|
||||
}
|
||||
|
||||
func GetSingleSession(id string) *Session {
|
||||
owner, name, application := util.GetOwnerAndNameAndOtherFromId(id)
|
||||
session := Session{Owner: owner, Name: name, Application: application}
|
||||
get, err := adapter.Engine.Get(&session)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !get {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &session
|
||||
}
|
||||
|
||||
func UpdateSession(id string, session *Session) bool {
|
||||
owner, name, application := util.GetOwnerAndNameAndOtherFromId(id)
|
||||
|
||||
if GetSingleSession(id) == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Update(session)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0
|
||||
}
|
||||
|
||||
func removeExtraSessionIds(session *Session) {
|
||||
if len(session.SessionId) > 100 {
|
||||
session.SessionId = session.SessionId[(len(session.SessionId) - 100):]
|
||||
}
|
||||
}
|
||||
|
||||
func AddSession(session *Session) bool {
|
||||
dbSession := GetSingleSession(session.GetId())
|
||||
if dbSession == nil {
|
||||
session.CreatedTime = util.GetCurrentTime()
|
||||
|
||||
affected, err := adapter.Engine.Insert(session)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0
|
||||
} else {
|
||||
m := make(map[string]struct{})
|
||||
for _, v := range dbSession.SessionId {
|
||||
m[v] = struct{}{}
|
||||
}
|
||||
for _, v := range session.SessionId {
|
||||
if _, exists := m[v]; !exists {
|
||||
dbSession.SessionId = append(dbSession.SessionId, v)
|
||||
}
|
||||
}
|
||||
|
||||
removeExtraSessionIds(dbSession)
|
||||
|
||||
return UpdateSession(dbSession.GetId(), dbSession)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteSession(id string) bool {
|
||||
owner, name, application := util.GetOwnerAndNameAndOtherFromId(id)
|
||||
if owner == CasdoorOrganization && application == CasdoorApplication {
|
||||
session := GetSingleSession(id)
|
||||
if session != nil {
|
||||
DeleteBeegoSession(session.SessionId)
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Delete(&Session{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0
|
||||
}
|
||||
|
||||
func DeleteSessionId(id string, sessionId string) bool {
|
||||
session := GetSingleSession(id)
|
||||
if session == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
owner, _, application := util.GetOwnerAndNameAndOtherFromId(id)
|
||||
if owner == CasdoorOrganization && application == CasdoorApplication {
|
||||
DeleteBeegoSession([]string{sessionId})
|
||||
}
|
||||
|
||||
session.SessionId = util.DeleteVal(session.SessionId, sessionId)
|
||||
if len(session.SessionId) == 0 {
|
||||
return DeleteSession(id)
|
||||
} else {
|
||||
return UpdateSession(id, session)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteBeegoSession(sessionIds []string) {
|
||||
for _, sessionId := range sessionIds {
|
||||
err := beego.GlobalSessions.GetProvider().SessionDestroy(sessionId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (session *Session) GetId() string {
|
||||
return fmt.Sprintf("%s/%s/%s", session.Owner, session.Name, session.Application)
|
||||
}
|
||||
|
||||
func IsSessionDuplicated(id string, sessionId string) bool {
|
||||
session := GetSingleSession(id)
|
||||
if session == nil {
|
||||
return false
|
||||
} else {
|
||||
if len(session.SessionId) > 1 {
|
||||
return true
|
||||
} else if len(session.SessionId) < 1 {
|
||||
return false
|
||||
} else {
|
||||
return session.SessionId[0] != sessionId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
@@ -54,6 +55,25 @@ func escapePath(path string) string {
|
||||
return res
|
||||
}
|
||||
|
||||
func GetTruncatedPath(provider *Provider, fullFilePath string, limit int) string {
|
||||
pathPrefix := util.UrlJoin(util.GetUrlPath(provider.Domain), provider.PathPrefix)
|
||||
|
||||
dir, file := filepath.Split(fullFilePath)
|
||||
ext := filepath.Ext(file)
|
||||
fileName := strings.TrimSuffix(file, ext)
|
||||
for {
|
||||
escapedString := escapePath(escapePath(fullFilePath))
|
||||
if len(escapedString) < limit-len(pathPrefix) {
|
||||
break
|
||||
}
|
||||
rs := []rune(fileName)
|
||||
fileName = string(rs[0 : len(rs)-1])
|
||||
fullFilePath = dir + fileName + ext
|
||||
}
|
||||
|
||||
return fullFilePath
|
||||
}
|
||||
|
||||
func GetUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
||||
escapedPath := util.UrlJoin(provider.PathPrefix, escapePath(fullFilePath))
|
||||
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type TableColumn struct {
|
||||
|
@@ -20,7 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type OriginalUser = User
|
||||
|
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/idp"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -321,7 +321,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
||||
}
|
||||
}
|
||||
|
||||
func GetOAuthToken(grantType string, clientId string, clientSecret string, code string, verifier string, scope string, username string, password string, host string, tag string, avatar string, lang string) interface{} {
|
||||
func GetOAuthToken(grantType string, clientId string, clientSecret string, code string, verifier string, scope string, username string, password string, host string, refreshToken string, tag string, avatar string, lang string) interface{} {
|
||||
application := GetApplicationByClientId(clientId)
|
||||
if application == nil {
|
||||
return &TokenError{
|
||||
@@ -348,6 +348,8 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
|
||||
token, tokenError = GetPasswordToken(application, username, password, scope, host)
|
||||
case "client_credentials": // Client Credentials Grant
|
||||
token, tokenError = GetClientCredentialsToken(application, clientSecret, scope, host)
|
||||
case "refresh_token":
|
||||
return RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||
}
|
||||
|
||||
if tag == "wechat_miniprogram" {
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/duo-labs/webauthn/webauthn"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -578,7 +578,7 @@ func AddUsersInBatch(users []*User) bool {
|
||||
|
||||
func DeleteUser(user *User) bool {
|
||||
// Forced offline the user first
|
||||
DeleteSession(user.GetId())
|
||||
DeleteSession(util.GetSessionId(user.Owner, user.Name, CasdoorApplication))
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
|
||||
if err != nil {
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
func updateUserColumn(column string, user *User) bool {
|
||||
|
@@ -20,7 +20,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/idp"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
func GetUserByField(organizationName string, field string, value string) *User {
|
||||
|
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
|
@@ -163,7 +163,11 @@ func initAPI() {
|
||||
beego.Router("/api/add-record", &controllers.ApiController{}, "POST:AddRecord")
|
||||
|
||||
beego.Router("/api/get-sessions", &controllers.ApiController{}, "GET:GetSessions")
|
||||
beego.Router("/api/get-session", &controllers.ApiController{}, "GET:GetSingleSession")
|
||||
beego.Router("/api/update-session", &controllers.ApiController{}, "POST:UpdateSession")
|
||||
beego.Router("/api/add-session", &controllers.ApiController{}, "POST:AddSession")
|
||||
beego.Router("/api/delete-session", &controllers.ApiController{}, "POST:DeleteSession")
|
||||
beego.Router("/api/is-session-duplicated", &controllers.ApiController{}, "GET:IsSessionDuplicated")
|
||||
|
||||
beego.Router("/api/get-webhooks", &controllers.ApiController{}, "GET:GetWebhooks")
|
||||
beego.Router("/api/get-webhook", &controllers.ApiController{}, "GET:GetWebhook")
|
||||
|
@@ -100,6 +100,15 @@ func GetOwnerAndNameFromIdNoCheck(id string) (string, string) {
|
||||
return tokens[0], tokens[1]
|
||||
}
|
||||
|
||||
func GetOwnerAndNameAndOtherFromId(id string) (string, string, string) {
|
||||
tokens := strings.Split(id, "/")
|
||||
if len(tokens) != 3 {
|
||||
panic(errors.New("GetOwnerAndNameAndOtherFromId() error, wrong token count for ID: " + id))
|
||||
}
|
||||
|
||||
return tokens[0], tokens[1], tokens[2]
|
||||
}
|
||||
|
||||
func GenerateId() string {
|
||||
return uuid.NewString()
|
||||
}
|
||||
@@ -127,6 +136,10 @@ func GetId(owner, name string) string {
|
||||
return fmt.Sprintf("%s/%s", owner, name)
|
||||
}
|
||||
|
||||
func GetSessionId(owner, name, application string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", owner, name, application)
|
||||
}
|
||||
|
||||
func GetMd5Hash(text string) string {
|
||||
hash := md5.Sum([]byte(text))
|
||||
return hex.EncodeToString(hash[:])
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
package util
|
||||
|
||||
import xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
import xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
|
||||
func CasbinToSlice(casbinRule xormadapter.CasbinRule) []string {
|
||||
s := []string{
|
||||
|
@@ -84,8 +84,8 @@ class App extends Component {
|
||||
uri: null,
|
||||
menuVisible: false,
|
||||
themeAlgorithm: ["default"],
|
||||
themeData: Setting.ThemeDefault,
|
||||
logo: this.getLogo(Setting.getAlgorithmNames(Setting.ThemeDefault)),
|
||||
themeData: Conf.ThemeDefault,
|
||||
logo: this.getLogo(Setting.getAlgorithmNames(Conf.ThemeDefault)),
|
||||
};
|
||||
|
||||
Setting.initServerUrl();
|
||||
|
@@ -18,6 +18,7 @@ import {CopyOutlined, LinkOutlined, UploadOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as CertBackend from "./backend/CertBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Conf from "./Conf";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as ResourceBackend from "./backend/ResourceBackend";
|
||||
@@ -717,7 +718,7 @@ class ApplicationEditPage extends React.Component {
|
||||
<Col span={22} style={{marginTop: "5px"}}>
|
||||
<Row>
|
||||
<Radio.Group value={this.state.application.themeData?.isEnabled ?? false} onChange={e => {
|
||||
const {_, ...theme} = this.state.application.themeData ?? {...Setting.ThemeDefault, isEnabled: false};
|
||||
const {_, ...theme} = this.state.application.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateApplicationField("themeData", {...theme, isEnabled: e.target.value});
|
||||
}} >
|
||||
<Radio.Button value={false}>{i18next.t("application:Follow organization theme")}</Radio.Button>
|
||||
@@ -728,7 +729,7 @@ class ApplicationEditPage extends React.Component {
|
||||
this.state.application.themeData?.isEnabled ?
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<ThemeEditor themeData={this.state.application.themeData} onThemeChange={(_, nextThemeData) => {
|
||||
const {isEnabled} = this.state.application.themeData ?? {...Setting.ThemeDefault, isEnabled: false};
|
||||
const {isEnabled} = this.state.application.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateApplicationField("themeData", {...nextThemeData, isEnabled});
|
||||
}} />
|
||||
</Row> : null
|
||||
@@ -764,7 +765,7 @@ class ApplicationEditPage extends React.Component {
|
||||
}
|
||||
|
||||
renderSignupSigninPreview() {
|
||||
const themeData = this.state.application.themeData ?? Setting.ThemeDefault;
|
||||
const themeData = this.state.application.themeData ?? Conf.ThemeDefault;
|
||||
let signUpUrl = `/signup/${this.state.application.name}`;
|
||||
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
|
||||
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "97%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
||||
@@ -835,7 +836,7 @@ class ApplicationEditPage extends React.Component {
|
||||
}
|
||||
|
||||
renderPromptPreview() {
|
||||
const themeData = this.state.application.themeData ?? Setting.ThemeDefault;
|
||||
const themeData = this.state.application.themeData ?? Conf.ThemeDefault;
|
||||
const promptUrl = `/prompt/${this.state.application.name}`;
|
||||
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
||||
return (
|
||||
|
@@ -17,6 +17,13 @@ export const GithubRepo = "https://github.com/casdoor/casdoor";
|
||||
|
||||
export const ForceLanguage = "";
|
||||
export const DefaultLanguage = "en";
|
||||
export const InitThemeAlgorithm = true;
|
||||
|
||||
export const EnableExtraPages = true;
|
||||
|
||||
export const InitThemeAlgorithm = true;
|
||||
export const ThemeDefault = {
|
||||
themeType: "default",
|
||||
colorPrimary: "#5734d3",
|
||||
borderRadius: 6,
|
||||
isCompact: false,
|
||||
};
|
||||
|
@@ -17,6 +17,7 @@ import {Redirect, Route, Switch} from "react-router-dom";
|
||||
import {Spin} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Conf from "./Conf";
|
||||
import SignupPage from "./auth/SignupPage";
|
||||
import SelfLoginPage from "./auth/SelfLoginPage";
|
||||
import LoginPage from "./auth/LoginPage";
|
||||
@@ -62,7 +63,7 @@ class EntryPage extends React.Component {
|
||||
application: application,
|
||||
});
|
||||
|
||||
const themeData = application !== null ? Setting.getThemeData(application.organizationObj, application) : Setting.ThemeDefault;
|
||||
const themeData = application !== null ? Setting.getThemeData(application.organizationObj, application) : Conf.ThemeDefault;
|
||||
this.props.updataThemeData(themeData);
|
||||
};
|
||||
|
||||
|
@@ -18,6 +18,7 @@ import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as LdapBackend from "./backend/LdapBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Conf from "./Conf";
|
||||
import i18next from "i18next";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import LdapTable from "./LdapTable";
|
||||
@@ -324,7 +325,7 @@ class OrganizationEditPage extends React.Component {
|
||||
<Col span={22} style={{marginTop: "5px"}}>
|
||||
<Row>
|
||||
<Radio.Group value={this.state.organization.themeData?.isEnabled ?? false} onChange={e => {
|
||||
const {_, ...theme} = this.state.organization.themeData ?? {...Setting.ThemeDefault, isEnabled: false};
|
||||
const {_, ...theme} = this.state.organization.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateOrganizationField("themeData", {...theme, isEnabled: e.target.value});
|
||||
}} >
|
||||
<Radio.Button value={false}>{i18next.t("organization:Follow global theme")}</Radio.Button>
|
||||
@@ -335,7 +336,7 @@ class OrganizationEditPage extends React.Component {
|
||||
this.state.organization.themeData?.isEnabled ?
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<ThemeEditor themeData={this.state.organization.themeData} onThemeChange={(_, nextThemeData) => {
|
||||
const {isEnabled} = this.state.organization.themeData ?? {...Setting.ThemeDefault, isEnabled: false};
|
||||
const {isEnabled} = this.state.organization.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateOrganizationField("themeData", {...nextThemeData, isEnabled});
|
||||
}} />
|
||||
</Row> : null
|
||||
|
@@ -17,7 +17,7 @@ import i18next from "i18next";
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import {CountDownInput} from "./common/CountDownInput";
|
||||
import {SendCodeInput} from "./common/SendCodeInput";
|
||||
import {MailOutlined, PhoneOutlined} from "@ant-design/icons";
|
||||
|
||||
export const ResetModal = (props) => {
|
||||
@@ -93,7 +93,7 @@ export const ResetModal = (props) => {
|
||||
/>
|
||||
</Row>
|
||||
<Row style={{width: "100%", marginBottom: "20px"}}>
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
textBefore={i18next.t("code:Code You Received")}
|
||||
onChange={setCode}
|
||||
method={"reset"}
|
||||
|
@@ -18,6 +18,16 @@ import {Dropdown} from "antd";
|
||||
import "./App.less";
|
||||
import {GlobalOutlined} from "@ant-design/icons";
|
||||
|
||||
export const Countries = [{label: "English", key: "en", country: "US", alt: "English"},
|
||||
{label: "简体中文", key: "zh", country: "CN", alt: "简体中文"},
|
||||
{label: "Español", key: "es", country: "ES", alt: "Español"},
|
||||
{label: "Français", key: "fr", country: "FR", alt: "Français"},
|
||||
{label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"},
|
||||
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
|
||||
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
||||
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
||||
];
|
||||
|
||||
function flagIcon(country, alt) {
|
||||
return (
|
||||
<img width={24} alt={alt} src={`${Setting.StaticBaseUrl}/flag-icons/${country}.svg`} />
|
||||
@@ -32,12 +42,12 @@ class SelectLanguageBox extends React.Component {
|
||||
languages: props.languages ?? ["en", "zh", "es", "fr", "de", "ja", "ko", "ru"],
|
||||
};
|
||||
|
||||
Setting.Countries.forEach((country) => {
|
||||
Countries.forEach((country) => {
|
||||
new Image().src = `${Setting.StaticBaseUrl}/flag-icons/${country.country}.svg`;
|
||||
});
|
||||
}
|
||||
|
||||
items = Setting.Countries.map((country) => Setting.getItem(country.label, country.key, flagIcon(country.country, country.alt)));
|
||||
items = Countries.map((country) => Setting.getItem(country.label, country.key, flagIcon(country.country, country.alt)));
|
||||
|
||||
getOrganizationLanguages(languages) {
|
||||
const select = [];
|
||||
|
@@ -49,8 +49,8 @@ class SelectRegionBox extends React.Component {
|
||||
}
|
||||
>
|
||||
{
|
||||
Setting.CountryRegionData.map((item, index) => (
|
||||
<Option key={index} value={item.code} label={`${item.name} (${item.code})`} >
|
||||
Setting.getCountryNames().map((item) => (
|
||||
<Option key={item.code} value={item.code} label={`${item.name} (${item.code})`} >
|
||||
<img src={`${Setting.StaticBaseUrl}/flag-icons/${item.code}.svg`} alt={item.name} height={20} style={{marginRight: 10}} />
|
||||
{`${item.name} (${item.code})`}
|
||||
</Option>
|
||||
|
@@ -30,33 +30,13 @@ export const ServerUrl = "";
|
||||
// export const StaticBaseUrl = "https://cdn.jsdelivr.net/gh/casbin/static";
|
||||
export const StaticBaseUrl = "https://cdn.casbin.org";
|
||||
|
||||
// https://catamphetamine.gitlab.io/country-flag-icons/3x2/index.html
|
||||
export const CountryRegionData = getCountryRegionData();
|
||||
|
||||
export const Countries = [{label: "English", key: "en", country: "US", alt: "English"},
|
||||
{label: "简体中文", key: "zh", country: "CN", alt: "简体中文"},
|
||||
{label: "Español", key: "es", country: "ES", alt: "Español"},
|
||||
{label: "Français", key: "fr", country: "FR", alt: "Français"},
|
||||
{label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"},
|
||||
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
|
||||
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
||||
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
||||
];
|
||||
|
||||
export const ThemeDefault = {
|
||||
themeType: "default",
|
||||
colorPrimary: "#5734d3",
|
||||
borderRadius: 6,
|
||||
isCompact: false,
|
||||
};
|
||||
|
||||
export function getThemeData(organization, application) {
|
||||
if (application?.themeData?.isEnabled) {
|
||||
return application.themeData;
|
||||
} else if (organization?.themeData?.isEnabled) {
|
||||
return organization.themeData;
|
||||
} else {
|
||||
return ThemeDefault;
|
||||
return Conf.ThemeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +98,12 @@ export const OtherProviderInfo = {
|
||||
url: "",
|
||||
},
|
||||
"SUBMAIL": {
|
||||
logo: `${StaticBaseUrl}/img/social_submail.png`,
|
||||
url: "",
|
||||
logo: `${StaticBaseUrl}/img/social_submail.svg`,
|
||||
url: "https://www.mysubmail.com",
|
||||
},
|
||||
"Mailtrap": {
|
||||
logo: `${StaticBaseUrl}/img/email_mailtrap.png`,
|
||||
url: "https://mailtrap.io",
|
||||
},
|
||||
},
|
||||
Storage: {
|
||||
@@ -204,18 +188,18 @@ export const OtherProviderInfo = {
|
||||
},
|
||||
};
|
||||
|
||||
export function getCountryRegionData() {
|
||||
let language = i18next.language;
|
||||
if (language === null || language === "null") {
|
||||
language = Conf.DefaultLanguage;
|
||||
}
|
||||
|
||||
export function getCountriesData() {
|
||||
const countries = require("i18n-iso-countries");
|
||||
countries.registerLocale(require("i18n-iso-countries/langs/" + language + ".json"));
|
||||
const data = countries.getNames(language, {select: "official"});
|
||||
const result = [];
|
||||
for (const i in data) {result.push({code: i, name: data[i]});}
|
||||
return result;
|
||||
countries.registerLocale(require("i18n-iso-countries/langs/" + getLanguage() + ".json"));
|
||||
return countries;
|
||||
}
|
||||
|
||||
export function getCountryNames() {
|
||||
const data = getCountriesData().getNames(getLanguage(), {select: "official"});
|
||||
|
||||
return Object.entries(data).map(items => {
|
||||
return {code: items[0], name: items[1]};
|
||||
});
|
||||
}
|
||||
|
||||
export function initServerUrl() {
|
||||
@@ -698,7 +682,7 @@ export function getLanguageText(text) {
|
||||
}
|
||||
|
||||
export function getLanguage() {
|
||||
return i18next.language;
|
||||
return i18next.language ?? Conf.DefaultLanguage;
|
||||
}
|
||||
|
||||
export function setLanguage(language) {
|
||||
@@ -839,6 +823,7 @@ export function getProviderTypeOptions(category) {
|
||||
[
|
||||
{id: "Default", name: "Default"},
|
||||
{id: "SUBMAIL", name: "SUBMAIL"},
|
||||
{id: "Mailtrap", name: "Mailtrap"},
|
||||
]
|
||||
);
|
||||
} else if (category === "SMS") {
|
||||
|
@@ -135,13 +135,6 @@ class UserListPage extends BaseListPage {
|
||||
}
|
||||
|
||||
renderTable(users) {
|
||||
// transfer country code to name based on selected language
|
||||
const countries = require("i18n-iso-countries");
|
||||
countries.registerLocale(require("i18n-iso-countries/langs/" + i18next.language + ".json"));
|
||||
for (const index in users) {
|
||||
users[index].region = countries.getName(users[index].region, i18next.language, {select: "official"});
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
@@ -267,6 +260,9 @@ class UserListPage extends BaseListPage {
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("region"),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getCountriesData().getName(record.region, Setting.getLanguage(), {select: "official"});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("user:Tag"),
|
||||
|
@@ -19,7 +19,7 @@ import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||
import * as Util from "./Util";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import {CountDownInput} from "../common/CountDownInput";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {CheckCircleOutlined, KeyOutlined, LockOutlined, SolutionOutlined, UserOutlined} from "@ant-design/icons";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
@@ -350,14 +350,14 @@ class ForgetPage extends React.Component {
|
||||
]}
|
||||
>
|
||||
{this.state.verifyType === "email" ? (
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
disabled={this.state.username === "" || this.state.verifyType === ""}
|
||||
method={"forget"}
|
||||
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(this.getApplicationObj()), this.state.name]}
|
||||
application={application}
|
||||
/>
|
||||
) : (
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
disabled={this.state.username === "" || this.state.verifyType === ""}
|
||||
method={"forget"}
|
||||
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(this.getApplicationObj()), this.state.name]}
|
||||
|
@@ -26,7 +26,7 @@ import * as Setting from "../Setting";
|
||||
import SelfLoginButton from "./SelfLoginButton";
|
||||
import i18next from "i18next";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
import {CountDownInput} from "../common/CountDownInput";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import SelectLanguageBox from "../SelectLanguageBox";
|
||||
import {CaptchaModal} from "../common/CaptchaModal";
|
||||
import RedirectForm from "../common/RedirectForm";
|
||||
@@ -419,7 +419,7 @@ class LoginPage extends React.Component {
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: i18next.t("login:Please input your username, Email or phone!"),
|
||||
message: i18next.t("login:Please input your Email or Phone!"),
|
||||
},
|
||||
{
|
||||
validator: (_, value) => {
|
||||
@@ -755,7 +755,7 @@ class LoginPage extends React.Component {
|
||||
name="code"
|
||||
rules={[{required: true, message: i18next.t("login:Please input your code!")}]}
|
||||
>
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
||||
method={"login"}
|
||||
onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]}
|
||||
|
@@ -21,7 +21,7 @@ import i18next from "i18next";
|
||||
import * as Util from "./Util";
|
||||
import {authConfig} from "./Auth";
|
||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||
import {CountDownInput} from "../common/CountDownInput";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import SelectRegionBox from "../SelectRegionBox";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
import SelectLanguageBox from "../SelectLanguageBox";
|
||||
@@ -365,7 +365,7 @@ class SignupPage extends React.Component {
|
||||
message: i18next.t("code:Please input your verification code!"),
|
||||
}]}
|
||||
>
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
disabled={!this.state.validEmail}
|
||||
method={"signup"}
|
||||
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(application)]}
|
||||
@@ -419,7 +419,7 @@ class SignupPage extends React.Component {
|
||||
},
|
||||
]}
|
||||
>
|
||||
<CountDownInput
|
||||
<SendCodeInput
|
||||
disabled={!this.state.validPhone}
|
||||
method={"signup"}
|
||||
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(application)]}
|
||||
|
@@ -109,7 +109,7 @@ export function setPassword(userOwner, userName, oldPassword, newPassword) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function sendCode(checkType, checkId, checkKey, method, dest, type, applicationId, checkUser) {
|
||||
export function sendCode(checkType, checkId, checkKey, method, dest, type, applicationId, checkUser = "") {
|
||||
const formData = new FormData();
|
||||
formData.append("checkType", checkType);
|
||||
formData.append("checkId", checkId);
|
||||
|
@@ -21,7 +21,7 @@ import {CaptchaWidget} from "./CaptchaWidget";
|
||||
|
||||
const {Search} = Input;
|
||||
|
||||
export const CountDownInput = (props) => {
|
||||
export const SendCodeInput = (props) => {
|
||||
const {disabled, textBefore, onChange, onButtonClickArgs, application, method} = props;
|
||||
const [visible, setVisible] = React.useState(false);
|
||||
const [key, setKey] = React.useState("");
|
@@ -14,14 +14,13 @@
|
||||
|
||||
import {Card, ConfigProvider, Form, Layout, Switch, theme} from "antd";
|
||||
import ThemePicker from "./ThemePicker";
|
||||
import ColorPicker from "./ColorPicker";
|
||||
import ColorPicker, {GREEN_COLOR, PINK_COLOR} from "./ColorPicker";
|
||||
import RadiusPicker from "./RadiusPicker";
|
||||
import * as React from "react";
|
||||
import {GREEN_COLOR, PINK_COLOR} from "./ColorPicker";
|
||||
import {useEffect} from "react";
|
||||
import {Content} from "antd/es/layout/layout";
|
||||
import i18next from "i18next";
|
||||
import {useEffect} from "react";
|
||||
import * as Setting from "../../Setting";
|
||||
import * as Conf from "../../Conf";
|
||||
|
||||
const ThemesInfo = {
|
||||
default: {},
|
||||
@@ -41,7 +40,7 @@ const ThemesInfo = {
|
||||
const onChange = () => {};
|
||||
|
||||
export default function ThemeEditor(props) {
|
||||
const themeData = props.themeData ?? Setting.ThemeDefault;
|
||||
const themeData = props.themeData ?? Conf.ThemeDefault;
|
||||
const onThemeChange = props.onThemeChange ?? onChange;
|
||||
|
||||
const {isCompact, themeType, ...themeToken} = themeData;
|
||||
@@ -59,7 +58,7 @@ export default function ThemeEditor(props) {
|
||||
}, [isLight, isCompact]);
|
||||
|
||||
useEffect(() => {
|
||||
const mergedData = Object.assign(Object.assign(Object.assign({}, Setting.ThemeDefault), {themeType}), ThemesInfo[themeType]);
|
||||
const mergedData = Object.assign(Object.assign(Object.assign({}, Conf.ThemeDefault), {themeType}), ThemesInfo[themeType]);
|
||||
onThemeChange(null, mergedData);
|
||||
form.setFieldsValue(mergedData);
|
||||
}, [themeType]);
|
||||
|
Reference in New Issue
Block a user