mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-23 14:33:28 +08:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
5315f16a48 | |||
d054f3e001 | |||
b158b840bd | |||
b16f1807b3 | |||
d0cce1bf7a | |||
9892cd20ab | |||
d1f31dd327 | |||
94743246a1 | |||
39ad1bc593 | |||
d97f833d2a | |||
948fa911e2 | |||
6073a0f63d | |||
91268bca70 | |||
23dbb0b926 |
@ -44,6 +44,8 @@ type Response struct {
|
||||
}
|
||||
|
||||
type Captcha struct {
|
||||
Owner string `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
AppKey string `json:"appKey"`
|
||||
Scene string `json:"scene"`
|
||||
@ -271,10 +273,8 @@ func (c *ApiController) Signup() {
|
||||
return
|
||||
}
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
c.Ctx.Input.SetParam("recordSignup", "true")
|
||||
|
||||
userId := user.GetId()
|
||||
util.LogInfo(c.Ctx, "API: [%s] is signed up as new user", userId)
|
||||
@ -532,10 +532,12 @@ func (c *ApiController) GetCaptcha() {
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(Captcha{Type: captchaProvider.Type, CaptchaId: id, CaptchaImage: img})
|
||||
c.ResponseOk(Captcha{Owner: captchaProvider.Owner, Name: captchaProvider.Name, Type: captchaProvider.Type, CaptchaId: id, CaptchaImage: img})
|
||||
return
|
||||
} else if captchaProvider.Type != "" {
|
||||
c.ResponseOk(Captcha{
|
||||
Owner: captchaProvider.Owner,
|
||||
Name: captchaProvider.Name,
|
||||
Type: captchaProvider.Type,
|
||||
SubType: captchaProvider.SubType,
|
||||
ClientId: captchaProvider.ClientId,
|
||||
|
@ -508,10 +508,7 @@ func (c *ApiController) Login() {
|
||||
|
||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
}
|
||||
} else if authForm.Provider != "" {
|
||||
var application *object.Application
|
||||
@ -632,10 +629,7 @@ func (c *ApiController) Login() {
|
||||
}
|
||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
} else if provider.Category == "OAuth" || provider.Category == "Web3" {
|
||||
// Sign up via OAuth
|
||||
if application.EnableLinkWithEmail {
|
||||
@ -768,16 +762,8 @@ func (c *ApiController) Login() {
|
||||
|
||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
|
||||
record2 := object.NewRecord(c.Ctx)
|
||||
record2.Action = "signup"
|
||||
record2.Organization = application.Organization
|
||||
record2.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record2) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
c.Ctx.Input.SetParam("recordSignup", "true")
|
||||
} else if provider.Category == "SAML" {
|
||||
// TODO: since we get the user info from SAML response, we can try to create the user
|
||||
resp = &Response{Status: "error", Msg: fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(application.Organization, userInfo.Id))}
|
||||
@ -879,10 +865,7 @@ func (c *ApiController) Login() {
|
||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||
c.setMfaUserSession("")
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
} else {
|
||||
if c.GetSessionUsername() != "" {
|
||||
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
||||
@ -901,10 +884,7 @@ func (c *ApiController) Login() {
|
||||
user := c.getCurrentUser()
|
||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
c.Ctx.Input.SetParam("recordUserId", user.GetId())
|
||||
} else {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:Unknown authentication type (not password or provider), form = %s"), util.StructToJson(authForm)))
|
||||
return
|
||||
|
@ -43,13 +43,20 @@ func (c *ApiController) GetGroups() {
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
} else {
|
||||
if withTree == "true" {
|
||||
c.ResponseOk(object.ConvertToTreeData(groups, owner))
|
||||
return
|
||||
}
|
||||
c.ResponseOk(groups)
|
||||
}
|
||||
|
||||
err = object.ExtendGroupsWithUsers(groups)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if withTree == "true" {
|
||||
c.ResponseOk(object.ConvertToTreeData(groups, owner))
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(groups)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetGroupCount(owner, field, value)
|
||||
@ -64,6 +71,12 @@ func (c *ApiController) GetGroups() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
} else {
|
||||
err = object.ExtendGroupsWithUsers(groups)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(groups, paginator.Nums())
|
||||
}
|
||||
}
|
||||
@ -84,6 +97,13 @@ func (c *ApiController) GetGroup() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = object.ExtendGroupWithUsers(group)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(group)
|
||||
}
|
||||
|
||||
|
@ -125,9 +125,11 @@ func (c *ApiController) SendEmail() {
|
||||
return
|
||||
}
|
||||
|
||||
userString := "Hi"
|
||||
if user != nil {
|
||||
content = strings.Replace(content, "%{user.friendlyName}", user.GetFriendlyName(), 1)
|
||||
userString = user.GetFriendlyName()
|
||||
}
|
||||
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@ func (c *ApiController) GetOAuthToken() {
|
||||
code := c.Input().Get("code")
|
||||
verifier := c.Input().Get("code_verifier")
|
||||
scope := c.Input().Get("scope")
|
||||
nonce := c.Input().Get("nonce")
|
||||
username := c.Input().Get("username")
|
||||
password := c.Input().Get("password")
|
||||
tag := c.Input().Get("tag")
|
||||
@ -197,6 +198,9 @@ func (c *ApiController) GetOAuthToken() {
|
||||
if scope == "" {
|
||||
scope = tokenRequest.Scope
|
||||
}
|
||||
if nonce == "" {
|
||||
nonce = tokenRequest.Nonce
|
||||
}
|
||||
if username == "" {
|
||||
username = tokenRequest.Username
|
||||
}
|
||||
@ -216,7 +220,7 @@ func (c *ApiController) GetOAuthToken() {
|
||||
}
|
||||
|
||||
host := c.Ctx.Request.Host
|
||||
token, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
||||
token, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, nonce, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
@ -21,6 +21,7 @@ type TokenRequest struct {
|
||||
Code string `json:"code"`
|
||||
Verifier string `json:"code_verifier"`
|
||||
Scope string `json:"scope"`
|
||||
Nonce string `json:"nonce"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Tag string `json:"tag"`
|
||||
|
1
main.go
1
main.go
@ -59,6 +59,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.ApiFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
beego.InsertFilter("*", beego.AfterExec, routers.AfterRecordMessage, false)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
|
@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -30,13 +31,13 @@ type Group struct {
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
UpdatedTime string `xorm:"varchar(100)" json:"updatedTime"`
|
||||
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Manager string `xorm:"varchar(100)" json:"manager"`
|
||||
ContactEmail string `xorm:"varchar(100)" json:"contactEmail"`
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
ParentId string `xorm:"varchar(100)" json:"parentId"`
|
||||
IsTopGroup bool `xorm:"bool" json:"isTopGroup"`
|
||||
Users []*User `xorm:"-" json:"users"`
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Manager string `xorm:"varchar(100)" json:"manager"`
|
||||
ContactEmail string `xorm:"varchar(100)" json:"contactEmail"`
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
ParentId string `xorm:"varchar(100)" json:"parentId"`
|
||||
IsTopGroup bool `xorm:"bool" json:"isTopGroup"`
|
||||
Users []string `xorm:"-" json:"users"`
|
||||
|
||||
Title string `json:"title,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
@ -288,6 +289,55 @@ func GetGroupUsers(groupId string) ([]*User, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func ExtendGroupWithUsers(group *Group) error {
|
||||
if group == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
users, err := GetUsers(group.Owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
groupId := group.GetId()
|
||||
userIds := []string{}
|
||||
for _, user := range users {
|
||||
if util.InSlice(user.Groups, groupId) {
|
||||
userIds = append(userIds, user.GetId())
|
||||
}
|
||||
}
|
||||
|
||||
group.Users = userIds
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtendGroupsWithUsers(groups []*Group) error {
|
||||
var wg sync.WaitGroup
|
||||
errChan := make(chan error, len(groups))
|
||||
|
||||
for _, group := range groups {
|
||||
wg.Add(1)
|
||||
go func(group *Group) {
|
||||
defer wg.Done()
|
||||
err := ExtendGroupWithUsers(group)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
}(group)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errChan)
|
||||
|
||||
for err := range errChan {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GroupChangeTrigger(oldName, newName string) error {
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
@ -15,6 +15,7 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -34,7 +35,12 @@ type Record struct {
|
||||
casvisorsdk.Record
|
||||
}
|
||||
|
||||
func NewRecord(ctx *context.Context) *casvisorsdk.Record {
|
||||
type Response struct {
|
||||
Status string `json:"status"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
|
||||
ip := strings.Replace(util.GetIPFromRequest(ctx.Request), ": ", "", -1)
|
||||
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
|
||||
requestUri := util.FilterQuery(ctx.Request.RequestURI, []string{"accessToken"})
|
||||
@ -47,6 +53,17 @@ func NewRecord(ctx *context.Context) *casvisorsdk.Record {
|
||||
object = string(ctx.Input.RequestBody)
|
||||
}
|
||||
|
||||
respBytes, err := json.Marshal(ctx.Input.Data()["json"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp Response
|
||||
err = json.Unmarshal(respBytes, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
language := ctx.Request.Header.Get("Accept-Language")
|
||||
if len(language) > 2 {
|
||||
language = language[0:2]
|
||||
@ -63,10 +80,10 @@ func NewRecord(ctx *context.Context) *casvisorsdk.Record {
|
||||
Action: action,
|
||||
Language: languageCode,
|
||||
Object: object,
|
||||
Response: "",
|
||||
Response: fmt.Sprintf("{status:\"%s\", msg:\"%s\"}", resp.Status, resp.Msg),
|
||||
IsTriggered: false,
|
||||
}
|
||||
return &record
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
func AddRecord(record *casvisorsdk.Record) bool {
|
||||
@ -123,6 +140,12 @@ func GetRecords() ([]*casvisorsdk.Record, error) {
|
||||
|
||||
func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder string, filterRecord *casvisorsdk.Record) ([]*casvisorsdk.Record, error) {
|
||||
records := []*casvisorsdk.Record{}
|
||||
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "id"
|
||||
sortOrder = "descend"
|
||||
}
|
||||
|
||||
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&records, filterRecord)
|
||||
if err != nil {
|
||||
@ -142,6 +165,25 @@ func GetRecordsByField(record *casvisorsdk.Record) ([]*casvisorsdk.Record, error
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func CopyRecord(record *casvisorsdk.Record) *casvisorsdk.Record {
|
||||
res := &casvisorsdk.Record{
|
||||
Owner: record.Owner,
|
||||
Name: record.Name,
|
||||
CreatedTime: record.CreatedTime,
|
||||
Organization: record.Organization,
|
||||
ClientIp: record.ClientIp,
|
||||
User: record.User,
|
||||
Method: record.Method,
|
||||
RequestUri: record.RequestUri,
|
||||
Action: record.Action,
|
||||
Language: record.Language,
|
||||
Object: record.Object,
|
||||
Response: record.Response,
|
||||
IsTriggered: record.IsTriggered,
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func getFilteredWebhooks(webhooks []*Webhook, organization string, action string) []*Webhook {
|
||||
res := []*Webhook{}
|
||||
for _, webhook := range webhooks {
|
||||
|
@ -189,7 +189,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
||||
}, nil
|
||||
}
|
||||
|
||||
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{}, error) {
|
||||
func GetOAuthToken(grantType string, clientId string, clientSecret string, code string, verifier string, scope string, nonce string, username string, password string, host string, refreshToken string, tag string, avatar string, lang string) (interface{}, error) {
|
||||
application, err := GetApplicationByClientId(clientId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -220,6 +220,8 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
|
||||
token, tokenError, err = GetPasswordToken(application, username, password, scope, host)
|
||||
case "client_credentials": // Client Credentials Grant
|
||||
token, tokenError, err = GetClientCredentialsToken(application, clientSecret, scope, host)
|
||||
case "token", "id_token": // Implicit Grant
|
||||
token, tokenError, err = GetImplicitToken(application, username, scope, nonce, host)
|
||||
case "refresh_token":
|
||||
refreshToken2, err := RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||
if err != nil {
|
||||
@ -582,6 +584,33 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
||||
return token, nil, nil
|
||||
}
|
||||
|
||||
// GetImplicitToken
|
||||
// Implicit flow
|
||||
func GetImplicitToken(application *Application, username string, scope string, nonce string, host string) (*Token, *TokenError, error) {
|
||||
user, err := GetUserByFields(application.Organization, username)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, &TokenError{
|
||||
Error: InvalidGrant,
|
||||
ErrorDescription: "the user does not exist",
|
||||
}, nil
|
||||
}
|
||||
if user.IsForbidden {
|
||||
return nil, &TokenError{
|
||||
Error: InvalidGrant,
|
||||
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
||||
}, nil
|
||||
}
|
||||
|
||||
token, err := GetTokenByUser(application, user, scope, nonce, host)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return token, nil, nil
|
||||
}
|
||||
|
||||
// GetTokenByUser
|
||||
// Implicit flow
|
||||
func GetTokenByUser(application *Application, user *User, scope string, nonce string, host string) (*Token, error) {
|
||||
|
@ -92,9 +92,12 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
|
||||
|
||||
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
|
||||
content := strings.Replace(provider.Content, "%s", code, 1)
|
||||
|
||||
userString := "Hi"
|
||||
if user != nil {
|
||||
content = strings.Replace(content, "%{user.friendlyName}", user.GetFriendlyName(), 1)
|
||||
userString = user.GetFriendlyName()
|
||||
}
|
||||
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
|
||||
|
||||
err := IsAllowSend(user, remoteAddr, provider.Category)
|
||||
if err != nil {
|
||||
@ -187,14 +190,17 @@ func CheckVerificationCode(dest string, code string, lang string) (*VerifyResult
|
||||
return &VerifyResult{noRecordError, i18n.Translate(lang, "verification:The verification code has not been sent yet, or has already been used!")}, nil
|
||||
}
|
||||
|
||||
timeout, err := conf.GetConfigInt64("verificationCodeTimeout")
|
||||
timeoutInMinutes, err := conf.GetConfigInt64("verificationCodeTimeout")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
if now-record.Time > timeout*60 {
|
||||
return &VerifyResult{timeoutError, fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeout)}, nil
|
||||
if now-record.Time > timeoutInMinutes*60*10 {
|
||||
return &VerifyResult{noRecordError, i18n.Translate(lang, "verification:The verification code has not been sent yet!")}, nil
|
||||
}
|
||||
if now-record.Time > timeoutInMinutes*60 {
|
||||
return &VerifyResult{timeoutError, fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeoutInMinutes)}, nil
|
||||
}
|
||||
|
||||
if record.Code != code {
|
||||
|
@ -20,6 +20,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/casdoor/casdoor/authz"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -211,5 +213,17 @@ func ApiFilter(ctx *context.Context) {
|
||||
|
||||
if !isAllowed {
|
||||
denyRequest(ctx)
|
||||
record, err := object.NewRecord(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
record.Organization = subOwner
|
||||
record.User = subName // auth:Unauthorized operation
|
||||
record.Response = fmt.Sprintf("{status:\"error\", msg:\"%s\"}", T(ctx, "auth:Unauthorized operation"))
|
||||
|
||||
util.SafeGoroutine(func() {
|
||||
object.AddRecord(record)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,12 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/casvisor/casvisor-go-sdk/casvisorsdk"
|
||||
)
|
||||
|
||||
func getUser(ctx *context.Context) (username string) {
|
||||
@ -60,12 +63,49 @@ func RecordMessage(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
record := object.NewRecord(ctx)
|
||||
|
||||
userId := getUser(ctx)
|
||||
|
||||
ctx.Input.SetParam("recordUserId", userId)
|
||||
}
|
||||
|
||||
func AfterRecordMessage(ctx *context.Context) {
|
||||
record, err := object.NewRecord(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("AfterRecordMessage() error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userId := ctx.Input.Params()["recordUserId"]
|
||||
if userId != "" {
|
||||
record.Organization, record.User = util.GetOwnerAndNameFromId(userId)
|
||||
}
|
||||
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
var record2 *casvisorsdk.Record
|
||||
recordSignup := ctx.Input.Params()["recordSignup"]
|
||||
if recordSignup == "true" {
|
||||
record2 = object.CopyRecord(record)
|
||||
record2.Action = "new-user"
|
||||
|
||||
var user *object.User
|
||||
user, err = object.GetUser(userId)
|
||||
if err != nil {
|
||||
fmt.Printf("AfterRecordMessage() error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
if user == nil {
|
||||
err = fmt.Errorf("the user: %s is not found", userId)
|
||||
fmt.Printf("AfterRecordMessage() error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
record2.Object = util.StructToJson(user)
|
||||
}
|
||||
|
||||
util.SafeGoroutine(func() {
|
||||
object.AddRecord(record)
|
||||
|
||||
if record2 != nil {
|
||||
object.AddRecord(record2)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ setTwoToneColor("rgb(87,52,211)");
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.setThemeAlgorithm();
|
||||
let storageThemeAlgorithm = [];
|
||||
try {
|
||||
storageThemeAlgorithm = localStorage.getItem("themeAlgorithm") ? JSON.parse(localStorage.getItem("themeAlgorithm")) : ["default"];
|
||||
@ -157,6 +158,15 @@ class App extends Component {
|
||||
return Setting.getLogo(themes);
|
||||
}
|
||||
|
||||
setThemeAlgorithm() {
|
||||
const currentUrl = window.location.href;
|
||||
const url = new URL(currentUrl);
|
||||
const themeType = url.searchParams.get("theme");
|
||||
if (themeType === "dark" || themeType === "default") {
|
||||
localStorage.setItem("themeAlgorithm", JSON.stringify([themeType]));
|
||||
}
|
||||
}
|
||||
|
||||
setLanguage(account) {
|
||||
const language = account?.language;
|
||||
if (language !== null && language !== "" && language !== i18next.language) {
|
||||
|
@ -456,6 +456,10 @@ class ApplicationEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableSigninSession} onChange={checked => {
|
||||
if (!checked) {
|
||||
this.updateApplicationField("enableAutoSignin", false);
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableSigninSession", checked);
|
||||
}} />
|
||||
</Col>
|
||||
@ -466,6 +470,11 @@ class ApplicationEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableAutoSignin} onChange={checked => {
|
||||
if (!this.state.application.enableSigninSession && checked) {
|
||||
Setting.showMessage("error", i18next.t("application:Please enable \"Signin session\" first before enabling \"Auto signin\""));
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableAutoSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
|
@ -177,6 +177,16 @@ class GroupEditPage extends React.Component {
|
||||
)} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Users"), i18next.t("general:Users - Tooltip"))} :
|
||||
</Col>
|
||||
<Col style={{marginTop: "5px"}} span={22} >
|
||||
{
|
||||
Setting.getTags(this.state.group.users, "users")
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
@ -195,6 +195,17 @@ class GroupListPage extends BaseListPage {
|
||||
</Link>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Users"),
|
||||
dataIndex: "users",
|
||||
key: "users",
|
||||
// width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("users"),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getTags(text, "users");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
@ -34,8 +34,8 @@ import OrganizationListPage from "./OrganizationListPage";
|
||||
import OrganizationEditPage from "./OrganizationEditPage";
|
||||
import UserListPage from "./UserListPage";
|
||||
import GroupTreePage from "./GroupTreePage";
|
||||
import GroupListPage from "./GroupList";
|
||||
import GroupEditPage from "./GroupEdit";
|
||||
import GroupListPage from "./GroupListPage";
|
||||
import GroupEditPage from "./GroupEditPage";
|
||||
import UserEditPage from "./UserEditPage";
|
||||
import InvitationListPage from "./InvitationListPage";
|
||||
import InvitationEditPage from "./InvitationEditPage";
|
||||
|
@ -151,6 +151,14 @@ class RecordListPage extends BaseListPage {
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("language"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("record:Response"),
|
||||
dataIndex: "response",
|
||||
key: "response",
|
||||
width: "90px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("response"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("record:Object"),
|
||||
dataIndex: "object",
|
||||
@ -179,7 +187,7 @@ class RecordListPage extends BaseListPage {
|
||||
sorter: true,
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
if (!["signup", "login", "logout", "update-user"].includes(record.action)) {
|
||||
if (!["signup", "login", "logout", "update-user", "new-user"].includes(record.action)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ class WebhookEditPage extends React.Component {
|
||||
}} >
|
||||
{
|
||||
(
|
||||
["signup", "login", "logout"].concat(this.getApiPaths()).map((option, index) => {
|
||||
["signup", "login", "logout", "new-user"].concat(this.getApiPaths()).map((option, index) => {
|
||||
return (
|
||||
<Option key={option} value={option}>{option}</Option>
|
||||
);
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Kopiere den Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copiar enlace",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copier le lien",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Salin Tautan",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "コピー リンク",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "링크 복사하기",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copiar Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Копировать ссылку",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Copy Link",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
"Object": "Object"
|
||||
"Object": "Object",
|
||||
"Response": "Response"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "Sao chép liên kết",
|
||||
|
@ -892,7 +892,8 @@
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "是否触发",
|
||||
"Object": "实体"
|
||||
"Object": "实体",
|
||||
"Response": "响应"
|
||||
},
|
||||
"resource": {
|
||||
"Copy Link": "复制链接",
|
||||
|
Reference in New Issue
Block a user