mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-31 00:30:32 +08:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
78dc660041 | ||
![]() |
2fb9674171 | ||
![]() |
55c522d3b7 | ||
![]() |
f879170663 | ||
![]() |
12e5d9b583 | ||
![]() |
eefa1e6df4 | ||
![]() |
026fb207b3 | ||
![]() |
ea10f8e615 | ||
![]() |
74b058aa3f | ||
![]() |
6c628d7893 | ||
![]() |
a38896e4d8 | ||
![]() |
5f054c4989 | ||
![]() |
fb16d8cee6 | ||
![]() |
5e4ba4f338 | ||
![]() |
ca47af2ee1 | ||
![]() |
59da104463 | ||
![]() |
c5bb916651 | ||
![]() |
e98264f957 | ||
![]() |
6a952952a8 | ||
![]() |
ba8a0f36be | ||
![]() |
b5e9084e5d | ||
![]() |
55d5ae10f2 | ||
![]() |
6986dad295 | ||
![]() |
949feb18af | ||
![]() |
d1f88ca9b8 |
141
ai/ai.go
141
ai/ai.go
@@ -1,141 +0,0 @@
|
||||
// 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 ai
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
func queryAnswer(authToken string, question string, timeout int) (string, error) {
|
||||
// fmt.Printf("Question: %s\n", question)
|
||||
|
||||
client := getProxyClientFromToken(authToken)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(2+timeout*2)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.CreateChatCompletion(
|
||||
ctx,
|
||||
openai.ChatCompletionRequest{
|
||||
Model: openai.GPT3Dot5Turbo,
|
||||
Messages: []openai.ChatCompletionMessage{
|
||||
{
|
||||
Role: openai.ChatMessageRoleUser,
|
||||
Content: question,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res := resp.Choices[0].Message.Content
|
||||
res = strings.Trim(res, "\n")
|
||||
// fmt.Printf("Answer: %s\n\n", res)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func QueryAnswerSafe(authToken string, question string) string {
|
||||
var res string
|
||||
var err error
|
||||
for i := 0; i < 10; i++ {
|
||||
res, err = queryAnswer(authToken, question, i)
|
||||
if err != nil {
|
||||
if i > 0 {
|
||||
fmt.Printf("\tFailed (%d): %s\n", i+1, err.Error())
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func QueryAnswerStream(authToken string, question string, writer io.Writer, builder *strings.Builder) error {
|
||||
client := getProxyClientFromToken(authToken)
|
||||
|
||||
ctx := context.Background()
|
||||
flusher, ok := writer.(http.Flusher)
|
||||
if !ok {
|
||||
return fmt.Errorf("writer does not implement http.Flusher")
|
||||
}
|
||||
// https://platform.openai.com/tokenizer
|
||||
// https://github.com/pkoukk/tiktoken-go#available-encodings
|
||||
promptTokens, err := getTokenSize(openai.GPT3TextDavinci003, question)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://platform.openai.com/docs/models/gpt-3-5
|
||||
maxTokens := 4097 - promptTokens
|
||||
|
||||
respStream, err := client.CreateCompletionStream(
|
||||
ctx,
|
||||
openai.CompletionRequest{
|
||||
Model: openai.GPT3TextDavinci003,
|
||||
Prompt: question,
|
||||
MaxTokens: maxTokens,
|
||||
Stream: true,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer respStream.Close()
|
||||
|
||||
isLeadingReturn := true
|
||||
for {
|
||||
completion, streamErr := respStream.Recv()
|
||||
if streamErr != nil {
|
||||
if streamErr == io.EOF {
|
||||
break
|
||||
}
|
||||
return streamErr
|
||||
}
|
||||
|
||||
data := completion.Choices[0].Text
|
||||
if isLeadingReturn && len(data) != 0 {
|
||||
if strings.Count(data, "\n") == len(data) {
|
||||
continue
|
||||
} else {
|
||||
isLeadingReturn = false
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s", data)
|
||||
|
||||
// Write the streamed data as Server-Sent Events
|
||||
if _, err = fmt.Fprintf(writer, "event: message\ndata: %s\n\n", data); err != nil {
|
||||
return err
|
||||
}
|
||||
flusher.Flush()
|
||||
// Append the response to the strings.Builder
|
||||
builder.WriteString(data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
// 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.
|
||||
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package ai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
object.InitConfig()
|
||||
proxy.InitHttpClient()
|
||||
|
||||
text, err := queryAnswer("", "hi", 5)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
println(text)
|
||||
}
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
println(getTokenSize(openai.GPT3TextDavinci003, ""))
|
||||
}
|
28
ai/proxy.go
28
ai/proxy.go
@@ -1,28 +0,0 @@
|
||||
// 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 ai
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
func getProxyClientFromToken(authToken string) *openai.Client {
|
||||
config := openai.DefaultConfig(authToken)
|
||||
config.HTTPClient = proxy.ProxyHttpClient
|
||||
|
||||
c := openai.NewClientWithConfig(config)
|
||||
return c
|
||||
}
|
28
ai/util.go
28
ai/util.go
@@ -1,28 +0,0 @@
|
||||
// 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 ai
|
||||
|
||||
import "github.com/pkoukk/tiktoken-go"
|
||||
|
||||
func getTokenSize(model string, prompt string) (int, error) {
|
||||
tkm, err := tiktoken.EncodingForModel(model)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
token := tkm.Encode(prompt, nil, nil)
|
||||
res := len(token)
|
||||
return res, nil
|
||||
}
|
@@ -18,56 +18,22 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
stringadapter "github.com/qiangmzsx/string-adapter/v2"
|
||||
)
|
||||
|
||||
var Enforcer *casbin.Enforcer
|
||||
|
||||
func InitAuthz() {
|
||||
func InitApi() {
|
||||
var err error
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
a, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, "casbin_rule", tableNamePrefix, true)
|
||||
e, err := object.GetEnforcer(util.GetId("built-in", "api-enforcer-built-in"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
modelText := `
|
||||
[request_definition]
|
||||
r = subOwner, subName, method, urlPath, objOwner, objName
|
||||
|
||||
[policy_definition]
|
||||
p = subOwner, subName, method, urlPath, objOwner, objName
|
||||
|
||||
[role_definition]
|
||||
g = _, _
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow))
|
||||
|
||||
[matchers]
|
||||
m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
|
||||
(r.subName == p.subName || p.subName == "*" || r.subName != "anonymous" && p.subName == "!anonymous") && \
|
||||
(r.method == p.method || p.method == "*") && \
|
||||
(r.urlPath == p.urlPath || p.urlPath == "*") && \
|
||||
(r.objOwner == p.objOwner || p.objOwner == "*") && \
|
||||
(r.objName == p.objName || p.objName == "*") || \
|
||||
(r.subOwner == r.objOwner && r.subName == r.objName)
|
||||
`
|
||||
|
||||
m, err := model.NewModelFromString(modelText)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Enforcer, err = casbin.NewEnforcer(m, a)
|
||||
Enforcer, err = e.InitEnforcer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -290,10 +290,11 @@ func (c *ApiController) Logout() {
|
||||
c.ResponseOk(user, application.HomepageUrl)
|
||||
return
|
||||
} else {
|
||||
if redirectUri == "" {
|
||||
c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
|
||||
return
|
||||
}
|
||||
// "post_logout_redirect_uri" has been made optional, see: https://github.com/casdoor/casdoor/issues/2151
|
||||
// if redirectUri == "" {
|
||||
// c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
|
||||
// return
|
||||
// }
|
||||
if accessToken == "" {
|
||||
c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint")
|
||||
return
|
||||
|
@@ -23,14 +23,14 @@ import (
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
// GetCasbinAdapters
|
||||
// @Title GetCasbinAdapters
|
||||
// GetAdapters
|
||||
// @Title GetAdapters
|
||||
// @Tag Adapter API
|
||||
// @Description get adapters
|
||||
// @Param owner query string true "The owner of adapters"
|
||||
// @Success 200 {array} object.Adapter The Response object
|
||||
// @router /get-adapters [get]
|
||||
func (c *ApiController) GetCasbinAdapters() {
|
||||
func (c *ApiController) GetAdapters() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
@@ -40,7 +40,7 @@ func (c *ApiController) GetCasbinAdapters() {
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
if limit == "" || page == "" {
|
||||
adapters, err := object.GetCasbinAdapters(owner)
|
||||
adapters, err := object.GetAdapters(owner)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -49,14 +49,14 @@ func (c *ApiController) GetCasbinAdapters() {
|
||||
c.ResponseOk(adapters)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetCasbinAdapterCount(owner, field, value)
|
||||
count, err := object.GetAdapterCount(owner, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
adapters, err := object.GetPaginationCasbinAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
adapters, err := object.GetPaginationAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -66,17 +66,17 @@ func (c *ApiController) GetCasbinAdapters() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetCasbinAdapter
|
||||
// @Title GetCasbinAdapter
|
||||
// GetAdapter
|
||||
// @Title GetAdapter
|
||||
// @Tag Adapter API
|
||||
// @Description get adapter
|
||||
// @Param id query string true "The id ( owner/name ) of the adapter"
|
||||
// @Success 200 {object} object.Adapter The Response object
|
||||
// @router /get-adapter [get]
|
||||
func (c *ApiController) GetCasbinAdapter() {
|
||||
func (c *ApiController) GetAdapter() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
adapter, err := object.GetCasbinAdapter(id)
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -85,75 +85,75 @@ func (c *ApiController) GetCasbinAdapter() {
|
||||
c.ResponseOk(adapter)
|
||||
}
|
||||
|
||||
// UpdateCasbinAdapter
|
||||
// @Title UpdateCasbinAdapter
|
||||
// UpdateAdapter
|
||||
// @Title UpdateAdapter
|
||||
// @Tag Adapter API
|
||||
// @Description update adapter
|
||||
// @Param id query string true "The id ( owner/name ) of the adapter"
|
||||
// @Param body body object.Adapter true "The details of the adapter"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /update-adapter [post]
|
||||
func (c *ApiController) UpdateCasbinAdapter() {
|
||||
func (c *ApiController) UpdateAdapter() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
var adapter object.Adapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateCasbinAdapter(id, &casbinAdapter))
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateAdapter(id, &adapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddCasbinAdapter
|
||||
// @Title AddCasbinAdapter
|
||||
// AddAdapter
|
||||
// @Title AddAdapter
|
||||
// @Tag Adapter API
|
||||
// @Description add adapter
|
||||
// @Param body body object.Adapter true "The details of the adapter"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /add-adapter [post]
|
||||
func (c *ApiController) AddCasbinAdapter() {
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
func (c *ApiController) AddAdapter() {
|
||||
var adapter object.Adapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddCasbinAdapter(&casbinAdapter))
|
||||
c.Data["json"] = wrapActionResponse(object.AddAdapter(&adapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteCasbinAdapter
|
||||
// @Title DeleteCasbinAdapter
|
||||
// DeleteAdapter
|
||||
// @Title DeleteAdapter
|
||||
// @Tag Adapter API
|
||||
// @Description delete adapter
|
||||
// @Param body body object.Adapter true "The details of the adapter"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /delete-adapter [post]
|
||||
func (c *ApiController) DeleteCasbinAdapter() {
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
func (c *ApiController) DeleteAdapter() {
|
||||
var adapter object.Adapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteCasbinAdapter(&casbinAdapter))
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteAdapter(&adapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) SyncPolicies() {
|
||||
func (c *ApiController) GetPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetCasbinAdapter(id)
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
policies, err := object.SyncPolicies(adapter)
|
||||
policies, err := object.GetPolicies(adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -164,7 +164,7 @@ func (c *ApiController) SyncPolicies() {
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetCasbinAdapter(id)
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -188,7 +188,7 @@ func (c *ApiController) UpdatePolicy() {
|
||||
|
||||
func (c *ApiController) AddPolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetCasbinAdapter(id)
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -212,7 +212,7 @@ func (c *ApiController) AddPolicy() {
|
||||
|
||||
func (c *ApiController) RemovePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetCasbinAdapter(id)
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
@@ -1,145 +0,0 @@
|
||||
// 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 controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// GetChats
|
||||
// @Title GetChats
|
||||
// @Tag Chat API
|
||||
// @Description get chats
|
||||
// @Param owner query string true "The owner of chats"
|
||||
// @Success 200 {array} object.Chat The Response object
|
||||
// @router /get-chats [get]
|
||||
func (c *ApiController) GetChats() {
|
||||
owner := "admin"
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
if limit == "" || page == "" {
|
||||
maskedChats, err := object.GetMaskedChats(object.GetChats(owner))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(maskedChats)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetChatCount(owner, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
chats, err := object.GetMaskedChats(object.GetPaginationChats(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(chats, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetChat
|
||||
// @Title GetChat
|
||||
// @Tag Chat API
|
||||
// @Description get chat
|
||||
// @Param id query string true "The id ( owner/name ) of the chat"
|
||||
// @Success 200 {object} object.Chat The Response object
|
||||
// @router /get-chat [get]
|
||||
func (c *ApiController) GetChat() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
maskedChat, err := object.GetMaskedChat(object.GetChat(id))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(maskedChat)
|
||||
}
|
||||
|
||||
// UpdateChat
|
||||
// @Title UpdateChat
|
||||
// @Tag Chat API
|
||||
// @Description update chat
|
||||
// @Param id query string true "The id ( owner/name ) of the chat"
|
||||
// @Param body body object.Chat true "The details of the chat"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /update-chat [post]
|
||||
func (c *ApiController) UpdateChat() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var chat object.Chat
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateChat(id, &chat))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddChat
|
||||
// @Title AddChat
|
||||
// @Tag Chat API
|
||||
// @Description add chat
|
||||
// @Param body body object.Chat true "The details of the chat"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /add-chat [post]
|
||||
func (c *ApiController) AddChat() {
|
||||
var chat object.Chat
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddChat(&chat))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteChat
|
||||
// @Title DeleteChat
|
||||
// @Tag Chat API
|
||||
// @Description delete chat
|
||||
// @Param body body object.Chat true "The details of the chat"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /delete-chat [post]
|
||||
func (c *ApiController) DeleteChat() {
|
||||
var chat object.Chat
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteChat(&chat))
|
||||
c.ServeJSON()
|
||||
}
|
145
controllers/enforcer.go
Normal file
145
controllers/enforcer.go
Normal file
@@ -0,0 +1,145 @@
|
||||
// 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 controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// GetEnforcers
|
||||
// @Title GetEnforcers
|
||||
// @Tag Enforcer API
|
||||
// @Description get enforcers
|
||||
// @Param owner query string true "The owner of enforcers"
|
||||
// @Success 200 {array} object.Enforcer
|
||||
// @router /get-enforcers [get]
|
||||
func (c *ApiController) GetEnforcers() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
if limit == "" || page == "" {
|
||||
enforcers, err := object.GetEnforcers(owner)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcers)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetEnforcerCount(owner, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
enforcers, err := object.GetPaginationEnforcers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcers, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetEnforcer
|
||||
// @Title GetEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description get enforcer
|
||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||
// @Success 200 {object} object
|
||||
// @router /get-enforcer [get]
|
||||
func (c *ApiController) GetEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
enforcer, err := object.GetEnforcer(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcer)
|
||||
}
|
||||
|
||||
// UpdateEnforcer
|
||||
// @Title UpdateEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description update enforcer
|
||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||
// @Param enforcer body object true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /update-enforcer [post]
|
||||
func (c *ApiController) UpdateEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
enforcer := object.Enforcer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateEnforcer(id, &enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddEnforcer
|
||||
// @Title AddEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description add enforcer
|
||||
// @Param enforcer body object true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /add-enforcer [post]
|
||||
func (c *ApiController) AddEnforcer() {
|
||||
enforcer := object.Enforcer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteEnforcer
|
||||
// @Title DeleteEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description delete enforcer
|
||||
// @Param body body object.Enforce true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /delete-enforcer [post]
|
||||
func (c *ApiController) DeleteEnforcer() {
|
||||
var enforcer object.Enforcer
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
@@ -1,313 +0,0 @@
|
||||
// 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 controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/ai"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// GetMessages
|
||||
// @Title GetMessages
|
||||
// @Tag Message API
|
||||
// @Description get messages
|
||||
// @Param owner query string true "The owner of messages"
|
||||
// @Success 200 {array} object.Message The Response object
|
||||
// @router /get-messages [get]
|
||||
func (c *ApiController) GetMessages() {
|
||||
owner := c.Input().Get("owner")
|
||||
organization := c.Input().Get("organization")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
chat := c.Input().Get("chat")
|
||||
|
||||
if limit == "" || page == "" {
|
||||
var messages []*object.Message
|
||||
var err error
|
||||
if chat == "" {
|
||||
messages, err = object.GetMessages(owner)
|
||||
} else {
|
||||
messages, err = object.GetChatMessages(chat)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetMaskedMessages(messages))
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetMessageCount(owner, organization, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
paginationMessages, err := object.GetPaginationMessages(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
messages := object.GetMaskedMessages(paginationMessages)
|
||||
c.ResponseOk(messages, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetMessage
|
||||
// @Title GetMessage
|
||||
// @Tag Message API
|
||||
// @Description get message
|
||||
// @Param id query string true "The id ( owner/name ) of the message"
|
||||
// @Success 200 {object} object.Message The Response object
|
||||
// @router /get-message [get]
|
||||
func (c *ApiController) GetMessage() {
|
||||
id := c.Input().Get("id")
|
||||
message, err := object.GetMessage(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(message)
|
||||
}
|
||||
|
||||
func (c *ApiController) ResponseErrorStream(errorText string) {
|
||||
event := fmt.Sprintf("event: myerror\ndata: %s\n\n", errorText)
|
||||
_, err := c.Ctx.ResponseWriter.Write([]byte(event))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// GetMessageAnswer
|
||||
// @Title GetMessageAnswer
|
||||
// @Tag Message API
|
||||
// @Description get message answer
|
||||
// @Param id query string true "The id ( owner/name ) of the message"
|
||||
// @Success 200 {object} object.Message The Response object
|
||||
// @router /get-message-answer [get]
|
||||
func (c *ApiController) GetMessageAnswer() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
|
||||
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
|
||||
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
|
||||
|
||||
message, err := object.GetMessage(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if message == nil {
|
||||
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
|
||||
return
|
||||
}
|
||||
|
||||
if message.Author != "AI" || message.ReplyTo == "" || message.Text != "" {
|
||||
c.ResponseErrorStream(c.T("chat:The message is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
chatId := util.GetId("admin", message.Chat)
|
||||
chat, err := object.GetChat(chatId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if chat == nil || chat.Organization != message.Organization {
|
||||
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
|
||||
return
|
||||
}
|
||||
|
||||
if chat.Type != "AI" {
|
||||
c.ResponseErrorStream(c.T("chat:The chat type must be \"AI\""))
|
||||
return
|
||||
}
|
||||
|
||||
questionMessage, err := object.GetMessage(message.ReplyTo)
|
||||
if questionMessage == nil {
|
||||
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
|
||||
return
|
||||
}
|
||||
|
||||
providerId := util.GetId(chat.Owner, chat.User2)
|
||||
provider, err := object.GetProvider(providerId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if provider == nil {
|
||||
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is not found"), providerId))
|
||||
return
|
||||
}
|
||||
|
||||
if provider.Category != "AI" || provider.ClientSecret == "" {
|
||||
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is invalid"), providerId))
|
||||
return
|
||||
}
|
||||
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
|
||||
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
|
||||
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
|
||||
|
||||
authToken := provider.ClientSecret
|
||||
question := questionMessage.Text
|
||||
var stringBuilder strings.Builder
|
||||
|
||||
fmt.Printf("Question: [%s]\n", questionMessage.Text)
|
||||
fmt.Printf("Answer: [")
|
||||
|
||||
err = ai.QueryAnswerStream(authToken, question, c.Ctx.ResponseWriter, &stringBuilder)
|
||||
if err != nil {
|
||||
c.ResponseErrorStream(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("]\n")
|
||||
|
||||
event := fmt.Sprintf("event: end\ndata: %s\n\n", "end")
|
||||
_, err = c.Ctx.ResponseWriter.Write([]byte(event))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
answer := stringBuilder.String()
|
||||
|
||||
message.Text = answer
|
||||
_, err = object.UpdateMessage(message.GetId(), message)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateMessage
|
||||
// @Title UpdateMessage
|
||||
// @Tag Message API
|
||||
// @Description update message
|
||||
// @Param id query string true "The id ( owner/name ) of the message"
|
||||
// @Param body body object.Message true "The details of the message"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /update-message [post]
|
||||
func (c *ApiController) UpdateMessage() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var message object.Message
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateMessage(id, &message))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddMessage
|
||||
// @Title AddMessage
|
||||
// @Tag Message API
|
||||
// @Description add message
|
||||
// @Param body body object.Message true "The details of the message"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /add-message [post]
|
||||
func (c *ApiController) AddMessage() {
|
||||
var message object.Message
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var chat *object.Chat
|
||||
if message.Chat != "" {
|
||||
chatId := util.GetId("admin", message.Chat)
|
||||
chat, err = object.GetChat(chatId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if chat == nil || chat.Organization != message.Organization {
|
||||
c.ResponseError(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := object.AddMessage(&message)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if affected {
|
||||
if chat != nil && chat.Type == "AI" {
|
||||
answerMessage := &object.Message{
|
||||
Owner: message.Owner,
|
||||
Name: fmt.Sprintf("message_%s", util.GetRandomName()),
|
||||
CreatedTime: util.GetCurrentTimeEx(message.CreatedTime),
|
||||
Organization: message.Organization,
|
||||
Chat: message.Chat,
|
||||
ReplyTo: message.GetId(),
|
||||
Author: "AI",
|
||||
Text: "",
|
||||
}
|
||||
_, err = object.AddMessage(answerMessage)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteMessage
|
||||
// @Title DeleteMessage
|
||||
// @Tag Message API
|
||||
// @Description delete message
|
||||
// @Param body body object.Message true "The details of the message"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /delete-message [post]
|
||||
func (c *ApiController) DeleteMessage() {
|
||||
var message object.Message
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteMessage(&message))
|
||||
c.ServeJSON()
|
||||
}
|
@@ -31,7 +31,6 @@ import (
|
||||
// @router /get-payments [get]
|
||||
func (c *ApiController) GetPayments() {
|
||||
owner := c.Input().Get("owner")
|
||||
organization := c.Input().Get("organization")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
@@ -49,14 +48,14 @@ func (c *ApiController) GetPayments() {
|
||||
c.ResponseOk(payments)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetPaymentCount(owner, organization, field, value)
|
||||
count, err := object.GetPaymentCount(owner, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
payments, err := object.GetPaginationPayments(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
payments, err := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -77,10 +76,9 @@ func (c *ApiController) GetPayments() {
|
||||
// @router /get-user-payments [get]
|
||||
func (c *ApiController) GetUserPayments() {
|
||||
owner := c.Input().Get("owner")
|
||||
organization := c.Input().Get("organization")
|
||||
user := c.Input().Get("user")
|
||||
|
||||
payments, err := object.GetUserPayments(owner, organization, user)
|
||||
payments, err := object.GetUserPayments(owner, user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -177,24 +175,18 @@ func (c *ApiController) DeletePayment() {
|
||||
// @router /notify-payment [post]
|
||||
func (c *ApiController) NotifyPayment() {
|
||||
owner := c.Ctx.Input.Param(":owner")
|
||||
providerName := c.Ctx.Input.Param(":provider")
|
||||
productName := c.Ctx.Input.Param(":product")
|
||||
paymentName := c.Ctx.Input.Param(":payment")
|
||||
orderId := c.Ctx.Input.Param("order")
|
||||
|
||||
body := c.Ctx.Input.RequestBody
|
||||
|
||||
err, errorResponse := object.NotifyPayment(c.Ctx.Request, body, owner, providerName, productName, paymentName, orderId)
|
||||
|
||||
_, err2 := c.Ctx.ResponseWriter.Write([]byte(errorResponse))
|
||||
if err2 != nil {
|
||||
panic(err2)
|
||||
}
|
||||
|
||||
payment, err := object.NotifyPayment(c.Ctx.Request, body, owner, paymentName, orderId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(payment)
|
||||
}
|
||||
|
||||
// InvoicePayment
|
||||
|
@@ -52,14 +52,6 @@ func (c *ApiController) GetResources() {
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
userObj, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if userObj.IsAdmin {
|
||||
user = ""
|
||||
}
|
||||
|
||||
if limit == "" || page == "" {
|
||||
resources, err := object.GetResources(owner, user)
|
||||
if err != nil {
|
||||
|
@@ -26,9 +26,10 @@ import (
|
||||
// @Title GetWebhooks
|
||||
// @Tag Webhook API
|
||||
// @Description get webhooks
|
||||
// @Param owner query string true "The owner of webhooks"
|
||||
// @Param owner query string built-in/admin true "The owner of webhooks"
|
||||
// @Success 200 {array} object.Webhook The Response object
|
||||
// @router /get-webhooks [get]
|
||||
// @Security test_apiKey
|
||||
func (c *ApiController) GetWebhooks() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
@@ -71,7 +72,7 @@ func (c *ApiController) GetWebhooks() {
|
||||
// @Title GetWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description get webhook
|
||||
// @Param id query string true "The id ( owner/name ) of the webhook"
|
||||
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
|
||||
// @Success 200 {object} object.Webhook The Response object
|
||||
// @router /get-webhook [get]
|
||||
func (c *ApiController) GetWebhook() {
|
||||
@@ -90,7 +91,7 @@ func (c *ApiController) GetWebhook() {
|
||||
// @Title UpdateWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description update webhook
|
||||
// @Param id query string true "The id ( owner/name ) of the webhook"
|
||||
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
|
||||
// @Param body body object.Webhook true "The details of the webhook"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /update-webhook [post]
|
||||
|
@@ -33,6 +33,9 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
||||
applyToOtherLanguage("frontend", "ru", data)
|
||||
applyToOtherLanguage("frontend", "vi", data)
|
||||
applyToOtherLanguage("frontend", "pt", data)
|
||||
applyToOtherLanguage("frontend", "it", data)
|
||||
applyToOtherLanguage("frontend", "ms", data)
|
||||
applyToOtherLanguage("frontend", "tr", data)
|
||||
}
|
||||
|
||||
func TestGenerateI18nBackend(t *testing.T) {
|
||||
@@ -49,4 +52,7 @@ func TestGenerateI18nBackend(t *testing.T) {
|
||||
applyToOtherLanguage("backend", "ru", data)
|
||||
applyToOtherLanguage("backend", "vi", data)
|
||||
applyToOtherLanguage("backend", "pt", data)
|
||||
applyToOtherLanguage("backend", "it", data)
|
||||
applyToOtherLanguage("backend", "ms", data)
|
||||
applyToOtherLanguage("backend", "tr", data)
|
||||
}
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
|
||||
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Los servicios %s y %s no coinciden"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Afiliación no puede estar en blanco",
|
||||
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation ne peut pas être vide",
|
||||
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
|
||||
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
|
||||
|
150
i18n/locales/it/data.json
Normal file
150
i18n/locales/it/data.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "サービス%sと%sは一致しません"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "所属は空白にできません",
|
||||
"DisplayName cannot be blank": "表示名は空白にできません",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
|
||||
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
|
||||
|
150
i18n/locales/ms/data.json
Normal file
150
i18n/locales/ms/data.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Сервисы %s и %s не совпадают"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
|
||||
"DisplayName cannot be blank": "Имя отображения не может быть пустым",
|
||||
|
150
i18n/locales/tr/data.json
Normal file
150
i18n/locales/tr/data.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
|
||||
"DisplayName cannot be blank": "Tên hiển thị không thể để trống",
|
||||
|
@@ -24,14 +24,6 @@
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "服务%s与%s不匹配"
|
||||
},
|
||||
"chat": {
|
||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
||||
"The chat: %s is not found": "The chat: %s is not found",
|
||||
"The message is invalid": "The message is invalid",
|
||||
"The message: %s is not found": "The message: %s is not found",
|
||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "工作单位不可为空",
|
||||
"DisplayName cannot be blank": "显示名称不可为空",
|
||||
|
@@ -21,15 +21,39 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const GoogleIdTokenKey = "GoogleIdToken"
|
||||
|
||||
type GoogleIdProvider struct {
|
||||
Client *http.Client
|
||||
Config *oauth2.Config
|
||||
}
|
||||
|
||||
// https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint
|
||||
type GoogleIdToken struct {
|
||||
// These six fields are included in all Google ID Tokens.
|
||||
Iss string `json:"iss"` // The issuer, or signer, of the token. For Google-signed ID tokens, this value is https://accounts.google.com.
|
||||
Sub string `json:"sub"` // The subject: the ID that represents the principal making the request.
|
||||
Azp string `json:"azp"` // Optional. Who the token was issued to. Here is the ClientID
|
||||
Aud string `json:"aud"` // The audience of the token. Here is the ClientID
|
||||
Iat string `json:"iat"` // Unix epoch time when the token was issued.
|
||||
Exp string `json:"exp"` // Unix epoch time when the token expires.
|
||||
// These seven fields are only included when the user has granted the "profile" and "email" OAuth scopes to the application.
|
||||
Email string `json:"email"`
|
||||
EmailVerified string `json:"email_verified"`
|
||||
Name string `json:"name"`
|
||||
Picture string `json:"picture"`
|
||||
GivenName string `json:"given_name"`
|
||||
FamilyName string `json:"family_name"`
|
||||
Locale string `json:"locale"`
|
||||
}
|
||||
|
||||
func NewGoogleIdProvider(clientId string, clientSecret string, redirectUrl string) *GoogleIdProvider {
|
||||
idp := &GoogleIdProvider{}
|
||||
|
||||
@@ -61,6 +85,25 @@ func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
|
||||
}
|
||||
|
||||
func (idp *GoogleIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
// Obtained the GoogleIdToken through Google OneTap authorization.
|
||||
if strings.HasPrefix(code, GoogleIdTokenKey) {
|
||||
code = strings.TrimPrefix(code, GoogleIdTokenKey+"-")
|
||||
var googleIdToken GoogleIdToken
|
||||
if err := json.Unmarshal([]byte(code), &googleIdToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expiry := int64(util.ParseInt(googleIdToken.Exp))
|
||||
token := &oauth2.Token{
|
||||
AccessToken: fmt.Sprintf("%v-%v", GoogleIdTokenKey, googleIdToken.Sub),
|
||||
TokenType: "Bearer",
|
||||
Expiry: time.Unix(expiry, 0),
|
||||
}
|
||||
token = token.WithExtra(map[string]interface{}{
|
||||
GoogleIdTokenKey: googleIdToken,
|
||||
})
|
||||
return token, nil
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, idp.Client)
|
||||
return idp.Config.Exchange(ctx, code)
|
||||
}
|
||||
@@ -88,6 +131,20 @@ type GoogleUserInfo struct {
|
||||
}
|
||||
|
||||
func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
if strings.HasPrefix(token.AccessToken, GoogleIdTokenKey) {
|
||||
googleIdToken, ok := token.Extra(GoogleIdTokenKey).(GoogleIdToken)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid googleIdToken")
|
||||
}
|
||||
userInfo := UserInfo{
|
||||
Id: googleIdToken.Sub,
|
||||
Username: googleIdToken.Email,
|
||||
DisplayName: googleIdToken.Name,
|
||||
Email: googleIdToken.Email,
|
||||
AvatarUrl: googleIdToken.Picture,
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
url := fmt.Sprintf("https://www.googleapis.com/oauth2/v2/userinfo?alt=json&access_token=%s", token.AccessToken)
|
||||
resp, err := idp.Client.Get(url)
|
||||
if err != nil {
|
||||
|
@@ -9,11 +9,11 @@
|
||||
"passwordType": "plain",
|
||||
"passwordSalt": "",
|
||||
"passwordOptions": ["AtLeast6"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR"],
|
||||
"defaultAvatar": "",
|
||||
"defaultApplication": "",
|
||||
"tags": [],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi"],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr"],
|
||||
"masterPassword": "",
|
||||
"initScore": 2000,
|
||||
"enableSoftDeletion": false,
|
||||
|
6
main.go
6
main.go
@@ -39,7 +39,7 @@ func getCreateDatabaseFlag() bool {
|
||||
func main() {
|
||||
createDatabase := getCreateDatabaseFlag()
|
||||
|
||||
object.InitAdapter()
|
||||
object.InitAdapter(createDatabase)
|
||||
object.CreateTables(createDatabase)
|
||||
object.DoMigration()
|
||||
|
||||
@@ -48,7 +48,7 @@ func main() {
|
||||
object.InitDefaultStorageProvider()
|
||||
object.InitLdapAutoSynchronizer()
|
||||
proxy.InitHttpClient()
|
||||
authz.InitAuthz()
|
||||
authz.InitApi()
|
||||
|
||||
util.SafeGoroutine(func() { object.RunSyncUsersJob() })
|
||||
|
||||
@@ -62,7 +62,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AutoSigninFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.ApiFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
// Copyright 2022 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.
|
||||
@@ -15,358 +15,310 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"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
|
||||
"github.com/xorm-io/core"
|
||||
"github.com/xorm-io/xorm"
|
||||
_ "modernc.org/sqlite" // db = sqlite
|
||||
)
|
||||
|
||||
var adapter *Adapter
|
||||
type Adapter 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"`
|
||||
|
||||
func InitConfig() {
|
||||
err := beego.LoadAppConfig("ini", "../conf/app.conf")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
|
||||
Host string `xorm:"varchar(100)" json:"host"`
|
||||
Port string `xorm:"varchar(20)" json:"port"`
|
||||
User string `xorm:"varchar(100)" json:"user"`
|
||||
Password string `xorm:"varchar(100)" json:"password"`
|
||||
Database string `xorm:"varchar(100)" json:"database"`
|
||||
Table string `xorm:"varchar(100)" json:"table"`
|
||||
TableNamePrefix string `xorm:"varchar(100)" json:"tableNamePrefix"`
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
InitAdapter()
|
||||
CreateTables(true)
|
||||
DoMigration()
|
||||
*xormadapter.Adapter `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
func InitAdapter() {
|
||||
err := createDatabaseForPostgres(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
|
||||
adapter.Engine.SetTableMapper(tbMapper)
|
||||
func GetAdapterCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Adapter{})
|
||||
}
|
||||
|
||||
func CreateTables(createDatabase bool) {
|
||||
if createDatabase {
|
||||
err := adapter.CreateDatabase()
|
||||
func GetAdapters(owner string) ([]*Adapter, error) {
|
||||
adapters := []*Adapter{}
|
||||
err := ormer.Engine.Desc("created_time").Find(&adapters, &Adapter{Owner: owner})
|
||||
if err != nil {
|
||||
return adapters, err
|
||||
}
|
||||
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
func GetPaginationAdapters(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Adapter, error) {
|
||||
adapters := []*Adapter{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&adapters)
|
||||
if err != nil {
|
||||
return adapters, err
|
||||
}
|
||||
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
func getAdapter(owner, name string) (*Adapter, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
adapter := Adapter{Owner: owner, Name: name}
|
||||
existed, err := ormer.Engine.Get(&adapter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &adapter, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetAdapter(id string) (*Adapter, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getAdapter(owner, name)
|
||||
}
|
||||
|
||||
func UpdateAdapter(id string, adapter *Adapter) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if adapter, err := getAdapter(owner, name); adapter == nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if name != adapter.Name {
|
||||
err := adapterChangeTrigger(name, adapter.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
adapter.createTable()
|
||||
}
|
||||
|
||||
// Adapter represents the MySQL adapter for policy storage.
|
||||
type Adapter struct {
|
||||
driverName string
|
||||
dataSourceName string
|
||||
dbName string
|
||||
Engine *xorm.Engine
|
||||
}
|
||||
|
||||
// finalizer is the destructor for Adapter.
|
||||
func finalizer(a *Adapter) {
|
||||
err := a.Engine.Close()
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if adapter.Password == "***" {
|
||||
session.Omit("password")
|
||||
}
|
||||
affected, err := session.Update(adapter)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddAdapter(adapter *Adapter) (bool, error) {
|
||||
affected, err := ormer.Engine.Insert(adapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteAdapter(adapter *Adapter) (bool, error) {
|
||||
affected, err := ormer.Engine.ID(core.PK{adapter.Owner, adapter.Name}).Delete(&Adapter{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (adapter *Adapter) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", adapter.Owner, adapter.Name)
|
||||
}
|
||||
|
||||
func (adapter *Adapter) getTable() string {
|
||||
if adapter.DatabaseType == "mssql" {
|
||||
return fmt.Sprintf("[%s]", adapter.Table)
|
||||
} else {
|
||||
return adapter.Table
|
||||
}
|
||||
}
|
||||
|
||||
// NewAdapter is the constructor for Adapter.
|
||||
func NewAdapter(driverName string, dataSourceName string, dbName string) *Adapter {
|
||||
a := &Adapter{}
|
||||
a.driverName = driverName
|
||||
a.dataSourceName = dataSourceName
|
||||
a.dbName = dbName
|
||||
func (adapter *Adapter) initAdapter() error {
|
||||
if adapter.Adapter == nil {
|
||||
var dataSourceName string
|
||||
|
||||
// Open the DB, create it if not existed.
|
||||
a.open()
|
||||
if adapter.buildInAdapter() {
|
||||
dataSourceName = conf.GetConfigString("dataSourceName")
|
||||
} else {
|
||||
switch adapter.DatabaseType {
|
||||
case "mssql":
|
||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%s?database=%s", adapter.User,
|
||||
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||
case "mysql":
|
||||
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%s)/", adapter.User,
|
||||
adapter.Password, adapter.Host, adapter.Port)
|
||||
case "postgres":
|
||||
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%s sslmode=disable dbname=%s", adapter.User,
|
||||
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||
case "CockroachDB":
|
||||
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%s sslmode=disable dbname=%s serial_normalization=virtual_sequence",
|
||||
adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||
case "sqlite3":
|
||||
dataSourceName = fmt.Sprintf("file:%s", adapter.Host)
|
||||
default:
|
||||
return fmt.Errorf("unsupported database type: %s", adapter.DatabaseType)
|
||||
}
|
||||
}
|
||||
|
||||
// Call the destructor when the object is released.
|
||||
runtime.SetFinalizer(a, finalizer)
|
||||
if !isCloudIntranet {
|
||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
|
||||
if driverName == "postgres" {
|
||||
db, err := sql.Open(driverName, dataSourceName)
|
||||
var err error
|
||||
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(adapter.DatabaseType, dataSourceName, adapter.Database).Engine, adapter.getTable(), adapter.TableNamePrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Adapter) CreateDatabase() error {
|
||||
if a.driverName == "postgres" {
|
||||
return nil
|
||||
}
|
||||
func adapterChangeTrigger(oldName string, newName string) error {
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
engine, err := xorm.NewEngine(a.driverName, a.dataSourceName)
|
||||
err := session.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer engine.Close()
|
||||
|
||||
_, err = engine.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s default charset utf8mb4 COLLATE utf8mb4_general_ci", a.dbName))
|
||||
return err
|
||||
enforcer := new(Enforcer)
|
||||
enforcer.Adapter = newName
|
||||
_, err = session.Where("adapter=?", oldName).Update(enforcer)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
func (a *Adapter) open() {
|
||||
dataSourceName := a.dataSourceName + a.dbName
|
||||
if a.driverName != "mysql" {
|
||||
dataSourceName = a.dataSourceName
|
||||
}
|
||||
|
||||
engine, err := xorm.NewEngine(a.driverName, dataSourceName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
a.Engine = engine
|
||||
}
|
||||
|
||||
func (a *Adapter) close() {
|
||||
_ = a.Engine.Close()
|
||||
a.Engine = nil
|
||||
}
|
||||
|
||||
func (a *Adapter) createTable() {
|
||||
showSql := conf.GetConfigBool("showSql")
|
||||
a.Engine.ShowSQL(showSql)
|
||||
|
||||
err := a.Engine.Sync2(new(Organization))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(User))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Group))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Role))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Permission))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Model))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(CasbinAdapter))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Provider))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Application))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Resource))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Token))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(VerificationRecord))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Record))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Webhook))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Syncer))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Cert))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Chat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Message))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Product))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Payment))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Ldap))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(PermissionRule))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(xormadapter.CasbinRule))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Session))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Subscription))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Plan))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Pricing))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := adapter.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
session = session.And("owner=?", owner)
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
func safeReturn(policy []string, i int) string {
|
||||
if len(policy) > i {
|
||||
return policy[i]
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
return ""
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := adapter.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
if offset == -1 {
|
||||
session = session.And("owner=?", owner)
|
||||
} else {
|
||||
session = session.And("a.owner=?", owner)
|
||||
func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
|
||||
res := []*xormadapter.CasbinRule{}
|
||||
|
||||
for _, policy := range policies {
|
||||
line := xormadapter.CasbinRule{
|
||||
Ptype: Ptype,
|
||||
V0: safeReturn(policy, 0),
|
||||
V1: safeReturn(policy, 1),
|
||||
V2: safeReturn(policy, 2),
|
||||
V3: safeReturn(policy, 3),
|
||||
V4: safeReturn(policy, 4),
|
||||
V5: safeReturn(policy, 5),
|
||||
}
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
if offset != -1 {
|
||||
field = fmt.Sprintf("a.%s", field)
|
||||
}
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
res = append(res, &line)
|
||||
}
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tableName := tableNamePrefix + "user"
|
||||
if offset == -1 {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
} else {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Asc("a." + util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Desc("a." + util.SnakeString(sortField))
|
||||
}
|
||||
}
|
||||
|
||||
return session
|
||||
return res
|
||||
}
|
||||
|
||||
func GetPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := matrixToCasbinRules("p", casbinModel.GetPolicy("p", "p"))
|
||||
policies = append(policies, matrixToCasbinRules("g", casbinModel.GetPolicy("g", "g"))...)
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.UpdatePolicy("p", "p", oldPolicy, newPolicy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func AddPolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel.AddPolicy("p", "p", policy)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func RemovePolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.RemovePolicy("p", "p", policy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func (adapter *Adapter) buildInAdapter() bool {
|
||||
if adapter.Owner != "built-in" {
|
||||
return false
|
||||
}
|
||||
|
||||
return adapter.Name == "permission-adapter-built-in" || adapter.Name == "api-adapter-built-in"
|
||||
}
|
||||
|
||||
func getModelDef() model.Model {
|
||||
casbinModel := model.NewModel()
|
||||
casbinModel.AddDef("p", "p", "_, _, _, _, _, _")
|
||||
casbinModel.AddDef("g", "g", "_, _, _, _, _, _")
|
||||
return casbinModel
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ func GetOrganizationApplicationCount(owner, Organization, field, value string) (
|
||||
|
||||
func GetApplications(owner string) ([]*Application, error) {
|
||||
applications := []*Application{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
|
||||
if err != nil {
|
||||
return applications, err
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func GetApplications(owner string) ([]*Application, error) {
|
||||
|
||||
func GetOrganizationApplications(owner string, organization string) ([]*Application, error) {
|
||||
applications := []*Application{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Organization: organization})
|
||||
err := ormer.Engine.Desc("created_time").Find(&applications, &Application{Organization: organization})
|
||||
if err != nil {
|
||||
return applications, err
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func getApplication(owner string, name string) (*Application, error) {
|
||||
}
|
||||
|
||||
application := Application{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&application)
|
||||
existed, err := ormer.Engine.Get(&application)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -206,7 +206,7 @@ func getApplication(owner string, name string) (*Application, error) {
|
||||
|
||||
func GetApplicationByOrganizationName(organization string) (*Application, error) {
|
||||
application := Application{}
|
||||
existed, err := adapter.Engine.Where("organization=?", organization).Get(&application)
|
||||
existed, err := ormer.Engine.Where("organization=?", organization).Get(&application)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func GetApplicationByUserId(userId string) (application *Application, err error)
|
||||
|
||||
func GetApplicationByClientId(clientId string) (*Application, error) {
|
||||
application := Application{}
|
||||
existed, err := adapter.Engine.Where("client_id=?", clientId).Get(&application)
|
||||
existed, err := ormer.Engine.Where("client_id=?", clientId).Get(&application)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -281,14 +281,21 @@ func GetApplication(id string) (*Application, error) {
|
||||
}
|
||||
|
||||
func GetMaskedApplication(application *Application, userId string) *Application {
|
||||
if isUserIdGlobalAdmin(userId) {
|
||||
return application
|
||||
}
|
||||
|
||||
if application == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if userId != "" {
|
||||
if isUserIdGlobalAdmin(userId) {
|
||||
return application
|
||||
}
|
||||
|
||||
user, _ := GetUser(userId)
|
||||
if user != nil && user.IsApplicationAdmin(application) {
|
||||
return application
|
||||
}
|
||||
}
|
||||
|
||||
if application.ClientSecret != "" {
|
||||
application.ClientSecret = "***"
|
||||
}
|
||||
@@ -349,7 +356,7 @@ func UpdateApplication(id string, application *Application) (bool, error) {
|
||||
providerItem.Provider = nil
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if application.ClientSecret == "***" {
|
||||
session.Omit("client_secret")
|
||||
}
|
||||
@@ -388,7 +395,7 @@ func AddApplication(application *Application) (bool, error) {
|
||||
providerItem.Provider = nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(application)
|
||||
affected, err := ormer.Engine.Insert(application)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@@ -401,7 +408,7 @@ func DeleteApplication(application *Application) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{application.Owner, application.Name}).Delete(&Application{})
|
||||
affected, err := ormer.Engine.ID(core.PK{application.Owner, application.Name}).Delete(&Application{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -477,7 +484,7 @@ func ExtendManagedAccountsWithUser(user *User) (*User, error) {
|
||||
}
|
||||
|
||||
func applicationChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -507,7 +514,7 @@ func applicationChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var permissions []*Permission
|
||||
err = adapter.Engine.Find(&permissions)
|
||||
err = ormer.Engine.Find(&permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -1,286 +0,0 @@
|
||||
// Copyright 2022 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 (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type CasbinAdapter 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"`
|
||||
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
|
||||
Host string `xorm:"varchar(100)" json:"host"`
|
||||
Port int `json:"port"`
|
||||
User string `xorm:"varchar(100)" json:"user"`
|
||||
Password string `xorm:"varchar(100)" json:"password"`
|
||||
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
|
||||
Database string `xorm:"varchar(100)" json:"database"`
|
||||
Table string `xorm:"varchar(100)" json:"table"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
Adapter *xormadapter.Adapter `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
func GetCasbinAdapterCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&CasbinAdapter{})
|
||||
}
|
||||
|
||||
func GetCasbinAdapters(owner string) ([]*CasbinAdapter, error) {
|
||||
adapters := []*CasbinAdapter{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&adapters, &CasbinAdapter{Owner: owner})
|
||||
if err != nil {
|
||||
return adapters, err
|
||||
}
|
||||
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
func GetPaginationCasbinAdapters(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*CasbinAdapter, error) {
|
||||
adapters := []*CasbinAdapter{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&adapters)
|
||||
if err != nil {
|
||||
return adapters, err
|
||||
}
|
||||
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
func getCasbinAdapter(owner, name string) (*CasbinAdapter, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
casbinAdapter := CasbinAdapter{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&casbinAdapter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &casbinAdapter, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetCasbinAdapter(id string) (*CasbinAdapter, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getCasbinAdapter(owner, name)
|
||||
}
|
||||
|
||||
func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if casbinAdapter, err := getCasbinAdapter(owner, name); casbinAdapter == nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if casbinAdapter.Password == "***" {
|
||||
session.Omit("password")
|
||||
}
|
||||
affected, err := session.Update(casbinAdapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(casbinAdapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{casbinAdapter.Owner, casbinAdapter.Name}).Delete(&CasbinAdapter{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (casbinAdapter *CasbinAdapter) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", casbinAdapter.Owner, casbinAdapter.Name)
|
||||
}
|
||||
|
||||
func (casbinAdapter *CasbinAdapter) getTable() string {
|
||||
if casbinAdapter.DatabaseType == "mssql" {
|
||||
return fmt.Sprintf("[%s]", casbinAdapter.Table)
|
||||
} else {
|
||||
return casbinAdapter.Table
|
||||
}
|
||||
}
|
||||
|
||||
func initEnforcer(modelObj *Model, casbinAdapter *CasbinAdapter) (*casbin.Enforcer, error) {
|
||||
// init Adapter
|
||||
if casbinAdapter.Adapter == nil {
|
||||
var dataSourceName string
|
||||
if casbinAdapter.DatabaseType == "mssql" {
|
||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port, casbinAdapter.Database)
|
||||
} else if casbinAdapter.DatabaseType == "postgres" {
|
||||
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port, casbinAdapter.Database)
|
||||
} else {
|
||||
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port)
|
||||
}
|
||||
|
||||
if !isCloudIntranet {
|
||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||
}
|
||||
|
||||
var err error
|
||||
casbinAdapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// init Model
|
||||
m, err := model.NewModelFromString(modelObj.ModelText)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// init Enforcer
|
||||
enforcer, err := casbin.NewEnforcer(m, casbinAdapter.Adapter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return enforcer, nil
|
||||
}
|
||||
|
||||
func safeReturn(policy []string, i int) string {
|
||||
if len(policy) > i {
|
||||
return policy[i]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
|
||||
res := []*xormadapter.CasbinRule{}
|
||||
|
||||
for _, policy := range policies {
|
||||
line := xormadapter.CasbinRule{
|
||||
Ptype: Ptype,
|
||||
V0: safeReturn(policy, 0),
|
||||
V1: safeReturn(policy, 1),
|
||||
V2: safeReturn(policy, 2),
|
||||
V3: safeReturn(policy, 3),
|
||||
V4: safeReturn(policy, 4),
|
||||
V5: safeReturn(policy, 5),
|
||||
}
|
||||
res = append(res, &line)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, error) {
|
||||
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if modelObj == nil {
|
||||
return nil, fmt.Errorf("The model: %s does not exist", util.GetId(casbinAdapter.Owner, casbinAdapter.Model))
|
||||
}
|
||||
|
||||
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := matrixToCasbinRules("p", enforcer.GetPolicy())
|
||||
if strings.Contains(modelObj.ModelText, "[role_definition]") {
|
||||
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
||||
}
|
||||
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected, err := enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected, err := enforcer.AddPolicy(policy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func RemovePolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected, err := enforcer.RemovePolicy(policy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
|
||||
return affected, nil
|
||||
}
|
@@ -65,7 +65,7 @@ func GetCertCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetCerts(owner string) ([]*Cert, error) {
|
||||
certs := []*Cert{}
|
||||
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
|
||||
err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
|
||||
if err != nil {
|
||||
return certs, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func GetGlobalCertsCount(field, value string) (int64, error) {
|
||||
|
||||
func GetGlobleCerts() ([]*Cert, error) {
|
||||
certs := []*Cert{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&certs)
|
||||
err := ormer.Engine.Desc("created_time").Find(&certs)
|
||||
if err != nil {
|
||||
return certs, err
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func getCert(owner string, name string) (*Cert, error) {
|
||||
}
|
||||
|
||||
cert := Cert{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&cert)
|
||||
existed, err := ormer.Engine.Get(&cert)
|
||||
if err != nil {
|
||||
return &cert, err
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func getCertByName(name string) (*Cert, error) {
|
||||
}
|
||||
|
||||
cert := Cert{Name: name}
|
||||
existed, err := adapter.Engine.Get(&cert)
|
||||
existed, err := ormer.Engine.Get(&cert)
|
||||
if err != nil {
|
||||
return &cert, nil
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func AddCert(cert *Cert) (bool, error) {
|
||||
cert.PrivateKey = privateKey
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(cert)
|
||||
affected, err := ormer.Engine.Insert(cert)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func AddCert(cert *Cert) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteCert(cert *Cert) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{cert.Owner, cert.Name}).Delete(&Cert{})
|
||||
affected, err := ormer.Engine.ID(core.PK{cert.Owner, cert.Name}).Delete(&Cert{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func GetDefaultCert() (*Cert, error) {
|
||||
}
|
||||
|
||||
func certChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
|
166
object/chat.go
166
object/chat.go
@@ -1,166 +0,0 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Chat 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"`
|
||||
UpdatedTime string `xorm:"varchar(100)" json:"updatedTime"`
|
||||
|
||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
Category string `xorm:"varchar(100)" json:"category"`
|
||||
User1 string `xorm:"varchar(100)" json:"user1"`
|
||||
User2 string `xorm:"varchar(100)" json:"user2"`
|
||||
Users []string `xorm:"varchar(100)" json:"users"`
|
||||
MessageCount int `json:"messageCount"`
|
||||
}
|
||||
|
||||
func GetMaskedChat(chat *Chat, err ...error) (*Chat, error) {
|
||||
if len(err) > 0 && err[0] != nil {
|
||||
return nil, err[0]
|
||||
}
|
||||
|
||||
if chat == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return chat, nil
|
||||
}
|
||||
|
||||
func GetMaskedChats(chats []*Chat, errs ...error) ([]*Chat, error) {
|
||||
if len(errs) > 0 && errs[0] != nil {
|
||||
return nil, errs[0]
|
||||
}
|
||||
var err error
|
||||
for _, chat := range chats {
|
||||
chat, err = GetMaskedChat(chat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return chats, nil
|
||||
}
|
||||
|
||||
func GetChatCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Chat{})
|
||||
}
|
||||
|
||||
func GetChats(owner string) ([]*Chat, error) {
|
||||
chats := []*Chat{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&chats, &Chat{Owner: owner})
|
||||
if err != nil {
|
||||
return chats, err
|
||||
}
|
||||
|
||||
return chats, nil
|
||||
}
|
||||
|
||||
func GetPaginationChats(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Chat, error) {
|
||||
chats := []*Chat{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&chats)
|
||||
if err != nil {
|
||||
return chats, err
|
||||
}
|
||||
|
||||
return chats, nil
|
||||
}
|
||||
|
||||
func getChat(owner string, name string) (*Chat, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
chat := Chat{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&chat)
|
||||
if err != nil {
|
||||
return &chat, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &chat, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetChat(id string) (*Chat, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getChat(owner, name)
|
||||
}
|
||||
|
||||
func UpdateChat(id string, chat *Chat) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if c, err := getChat(owner, name); err != nil {
|
||||
return false, err
|
||||
} else if c == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(chat)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddChat(chat *Chat) (bool, error) {
|
||||
if chat.Type == "AI" && chat.User2 == "" {
|
||||
provider, err := getDefaultAiProvider()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if provider != nil {
|
||||
chat.User2 = provider.Name
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(chat)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteChat(chat *Chat) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{chat.Owner, chat.Name}).Delete(&Chat{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if affected != 0 {
|
||||
return DeleteChatMessages(chat.Name)
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (p *Chat) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||
}
|
@@ -365,7 +365,7 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
||||
if containsAsterisk {
|
||||
return true, err
|
||||
}
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
|
||||
return allowed, err
|
||||
}
|
||||
|
163
object/enforcer.go
Normal file
163
object/enforcer.go
Normal file
@@ -0,0 +1,163 @@
|
||||
// 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/casbin/casbin/v2"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Enforcer 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"`
|
||||
UpdatedTime string `xorm:"varchar(100) updated" json:"updatedTime"`
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
*casbin.Enforcer
|
||||
}
|
||||
|
||||
func GetEnforcerCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Enforcer{})
|
||||
}
|
||||
|
||||
func GetEnforcers(owner string) ([]*Enforcer, error) {
|
||||
enforcers := []*Enforcer{}
|
||||
err := ormer.Engine.Desc("created_time").Find(&enforcers, &Enforcer{Owner: owner})
|
||||
if err != nil {
|
||||
return enforcers, err
|
||||
}
|
||||
|
||||
return enforcers, nil
|
||||
}
|
||||
|
||||
func GetPaginationEnforcers(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Enforcer, error) {
|
||||
enforcers := []*Enforcer{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&enforcers)
|
||||
if err != nil {
|
||||
return enforcers, err
|
||||
}
|
||||
|
||||
return enforcers, nil
|
||||
}
|
||||
|
||||
func getEnforcer(owner string, name string) (*Enforcer, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
enforcer := Enforcer{Owner: owner, Name: name}
|
||||
existed, err := ormer.Engine.Get(&enforcer)
|
||||
if err != nil {
|
||||
return &enforcer, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &enforcer, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetEnforcer(id string) (*Enforcer, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getEnforcer(owner, name)
|
||||
}
|
||||
|
||||
func UpdateEnforcer(id string, enforcer *Enforcer) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if oldEnforcer, err := getEnforcer(owner, name); err != nil {
|
||||
return false, err
|
||||
} else if oldEnforcer == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(enforcer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
affected, err := ormer.Engine.Insert(enforcer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
affected, err := ormer.Engine.ID(core.PK{enforcer.Owner, enforcer.Name}).Delete(&Enforcer{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (enforcer *Enforcer) InitEnforcer() (*casbin.Enforcer, error) {
|
||||
if enforcer == nil {
|
||||
return nil, errors.New("enforcer is nil")
|
||||
}
|
||||
if enforcer.Model == "" || enforcer.Adapter == "" {
|
||||
return nil, errors.New("missing model or adapter")
|
||||
}
|
||||
|
||||
var err error
|
||||
var m *Model
|
||||
var a *Adapter
|
||||
|
||||
if m, err = GetModel(enforcer.Model); err != nil {
|
||||
return nil, err
|
||||
} else if m == nil {
|
||||
return nil, errors.New("model not found")
|
||||
}
|
||||
|
||||
if a, err = GetAdapter(enforcer.Adapter); err != nil {
|
||||
return nil, err
|
||||
} else if a == nil {
|
||||
return nil, errors.New("adapter not found")
|
||||
}
|
||||
|
||||
err = m.initModel()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = a.initAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e, err := casbin.NewEnforcer(m.Model, a.Adapter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
@@ -58,7 +58,7 @@ func GetGroupCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetGroups(owner string) ([]*Group, error) {
|
||||
groups := []*Group{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&groups, &Group{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&groups, &Group{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func getGroup(owner string, name string) (*Group, error) {
|
||||
}
|
||||
|
||||
group := Group{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&group)
|
||||
existed, err := ormer.Engine.Get(&group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func UpdateGroup(id string, group *Group) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(group)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(group)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func AddGroup(group *Group) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(group)
|
||||
affected, err := ormer.Engine.Insert(group)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func AddGroups(groups []*Group) (bool, error) {
|
||||
if len(groups) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
affected, err := adapter.Engine.Insert(groups)
|
||||
affected, err := ormer.Engine.Insert(groups)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -153,12 +153,12 @@ func AddGroups(groups []*Group) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteGroup(group *Group) (bool, error) {
|
||||
_, err := adapter.Engine.Get(group)
|
||||
_, err := ormer.Engine.Get(group)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count, err := adapter.Engine.Where("parent_id = ?", group.Name).Count(&Group{}); err != nil {
|
||||
if count, err := ormer.Engine.Where("parent_id = ?", group.Name).Count(&Group{}); err != nil {
|
||||
return false, err
|
||||
} else if count > 0 {
|
||||
return false, errors.New("group has children group")
|
||||
@@ -170,7 +170,7 @@ func DeleteGroup(group *Group) (bool, error) {
|
||||
return false, errors.New("group has users")
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{group.Owner, group.Name}).Delete(&Group{})
|
||||
affected, err := ormer.Engine.ID(core.PK{group.Owner, group.Name}).Delete(&Group{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -179,7 +179,7 @@ func DeleteGroup(group *Group) (bool, error) {
|
||||
}
|
||||
|
||||
func checkGroupName(name string) error {
|
||||
exist, err := adapter.Engine.Exist(&Organization{Owner: "admin", Name: name})
|
||||
exist, err := ormer.Engine.Exist(&Organization{Owner: "admin", Name: name})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -233,10 +233,10 @@ func RemoveUserFromGroup(owner, name, groupName string) (bool, error) {
|
||||
|
||||
func GetGroupUserCount(groupName string, field, value string) (int64, error) {
|
||||
if field == "" && value == "" {
|
||||
return adapter.Engine.Where(builder.Like{"`groups`", groupName}).
|
||||
return ormer.Engine.Where(builder.Like{"`groups`", groupName}).
|
||||
Count(&User{})
|
||||
} else {
|
||||
return adapter.Engine.Table("user").
|
||||
return ormer.Engine.Table("user").
|
||||
Where(builder.Like{"`groups`", groupName}).
|
||||
And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%").
|
||||
Count()
|
||||
@@ -245,7 +245,7 @@ func GetGroupUserCount(groupName string, field, value string) (int64, error) {
|
||||
|
||||
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
|
||||
users := []*User{}
|
||||
session := adapter.Engine.Table("user").
|
||||
session := ormer.Engine.Table("user").
|
||||
Where(builder.Like{"`groups`", groupName + "\""})
|
||||
|
||||
if offset != -1 && limit != -1 {
|
||||
@@ -275,7 +275,7 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
|
||||
|
||||
func GetGroupUsers(groupName string) ([]*User, error) {
|
||||
users := []*User{}
|
||||
err := adapter.Engine.Table("user").
|
||||
err := ormer.Engine.Table("user").
|
||||
Where(builder.Like{"`groups`", groupName + "\""}).
|
||||
Find(&users)
|
||||
if err != nil {
|
||||
@@ -286,7 +286,7 @@ func GetGroupUsers(groupName string) ([]*User, error) {
|
||||
}
|
||||
|
||||
func GroupChangeTrigger(oldName, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
err := session.Begin()
|
||||
if err != nil {
|
||||
|
170
object/init.go
170
object/init.go
@@ -27,7 +27,6 @@ import (
|
||||
func InitDb() {
|
||||
existed := initBuiltInOrganization()
|
||||
if !existed {
|
||||
initBuiltInModel()
|
||||
initBuiltInPermission()
|
||||
initBuiltInProvider()
|
||||
initBuiltInUser()
|
||||
@@ -36,6 +35,15 @@ func InitDb() {
|
||||
initBuiltInLdap()
|
||||
}
|
||||
|
||||
existed = initBuiltInApiModel()
|
||||
if !existed {
|
||||
initBuildInApiAdapter()
|
||||
initBuiltInApiEnforcer()
|
||||
initBuiltInPermissionModel()
|
||||
initBuildInPermissionAdapter()
|
||||
initBuiltInPermissionEnforcer()
|
||||
}
|
||||
|
||||
initWebAuthn()
|
||||
}
|
||||
|
||||
@@ -295,8 +303,8 @@ func initWebAuthn() {
|
||||
gob.Register(webauthn.SessionData{})
|
||||
}
|
||||
|
||||
func initBuiltInModel() {
|
||||
model, err := GetModel("built-in/model-built-in")
|
||||
func initBuiltInPermissionModel() {
|
||||
model, err := GetModel("built-in/permission-model-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -307,7 +315,7 @@ func initBuiltInModel() {
|
||||
|
||||
model = &Model{
|
||||
Owner: "built-in",
|
||||
Name: "model-built-in",
|
||||
Name: "permission-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "Built-in Model",
|
||||
IsEnabled: true,
|
||||
@@ -329,6 +337,54 @@ m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`,
|
||||
}
|
||||
}
|
||||
|
||||
func initBuiltInApiModel() bool {
|
||||
model, err := GetModel("built-in/api-model-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if model != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
modelText := `
|
||||
[request_definition]
|
||||
r = subOwner, subName, method, urlPath, objOwner, objName
|
||||
|
||||
[policy_definition]
|
||||
p = subOwner, subName, method, urlPath, objOwner, objName
|
||||
|
||||
[role_definition]
|
||||
g = _, _
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow))
|
||||
|
||||
[matchers]
|
||||
m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
|
||||
(r.subName == p.subName || p.subName == "*" || r.subName != "anonymous" && p.subName == "!anonymous") && \
|
||||
(r.method == p.method || p.method == "*") && \
|
||||
(r.urlPath == p.urlPath || p.urlPath == "*") && \
|
||||
(r.objOwner == p.objOwner || p.objOwner == "*") && \
|
||||
(r.objName == p.objName || p.objName == "*") || \
|
||||
(r.subOwner == r.objOwner && r.subName == r.objName)
|
||||
`
|
||||
|
||||
model = &Model{
|
||||
Owner: "built-in",
|
||||
Name: "api-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "API Model",
|
||||
IsEnabled: true,
|
||||
ModelText: modelText,
|
||||
}
|
||||
_, err = AddModel(model)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func initBuiltInPermission() {
|
||||
permission, err := GetPermission("built-in/permission-built-in")
|
||||
if err != nil {
|
||||
@@ -358,3 +414,109 @@ func initBuiltInPermission() {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initBuildInPermissionAdapter() {
|
||||
permissionAdapter, err := GetAdapter("built-in/permission-adapter-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if permissionAdapter != nil {
|
||||
return
|
||||
}
|
||||
|
||||
permissionAdapter = &Adapter{
|
||||
Owner: "built-in",
|
||||
Name: "permission-adapter-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
Type: "Database",
|
||||
DatabaseType: conf.GetConfigString("driverName"),
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_user_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(permissionAdapter)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initBuildInApiAdapter() {
|
||||
apiAdapter, err := GetAdapter("built-in/api-adapter-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if apiAdapter != nil {
|
||||
return
|
||||
}
|
||||
|
||||
apiAdapter = &Adapter{
|
||||
Owner: "built-in",
|
||||
Name: "api-adapter-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
Type: "Database",
|
||||
DatabaseType: conf.GetConfigString("driverName"),
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_api_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(apiAdapter)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initBuiltInPermissionEnforcer() {
|
||||
permissionEnforcer, err := GetEnforcer("built-in/permission-enforcer-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if permissionEnforcer != nil {
|
||||
return
|
||||
}
|
||||
|
||||
permissionEnforcer = &Enforcer{
|
||||
Owner: "built-in",
|
||||
Name: "permission-enforcer-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "Permission Enforcer",
|
||||
Model: "built-in/permission-model-built-in",
|
||||
Adapter: "built-in/permission-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(permissionEnforcer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initBuiltInApiEnforcer() {
|
||||
apiEnforcer, err := GetEnforcer("built-in/api-enforcer-built-in")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if apiEnforcer != nil {
|
||||
return
|
||||
}
|
||||
|
||||
apiEnforcer = &Enforcer{
|
||||
Owner: "built-in",
|
||||
Name: "api-enforcer-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "API Enforcer",
|
||||
Model: "built-in/api-model-built-in",
|
||||
Adapter: "built-in/api-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(apiEnforcer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ func AddLdap(ldap *Ldap) (bool, error) {
|
||||
ldap.CreatedTime = util.GetCurrentTime()
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(ldap)
|
||||
affected, err := ormer.Engine.Insert(ldap)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func AddLdap(ldap *Ldap) (bool, error) {
|
||||
|
||||
func CheckLdapExist(ldap *Ldap) (bool, error) {
|
||||
var result []*Ldap
|
||||
err := adapter.Engine.Find(&result, &Ldap{
|
||||
err := ormer.Engine.Find(&result, &Ldap{
|
||||
Owner: ldap.Owner,
|
||||
Host: ldap.Host,
|
||||
Port: ldap.Port,
|
||||
@@ -77,7 +77,7 @@ func CheckLdapExist(ldap *Ldap) (bool, error) {
|
||||
|
||||
func GetLdaps(owner string) ([]*Ldap, error) {
|
||||
var ldaps []*Ldap
|
||||
err := adapter.Engine.Desc("created_time").Find(&ldaps, &Ldap{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&ldaps, &Ldap{Owner: owner})
|
||||
if err != nil {
|
||||
return ldaps, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func GetLdap(id string) (*Ldap, error) {
|
||||
}
|
||||
|
||||
ldap := Ldap{Id: id}
|
||||
existed, err := adapter.Engine.Get(&ldap)
|
||||
existed, err := ormer.Engine.Get(&ldap)
|
||||
if err != nil {
|
||||
return &ldap, nil
|
||||
}
|
||||
@@ -135,13 +135,19 @@ func GetMaskedLdaps(ldaps []*Ldap, errs ...error) ([]*Ldap, error) {
|
||||
}
|
||||
|
||||
func UpdateLdap(ldap *Ldap) (bool, error) {
|
||||
if l, err := GetLdap(ldap.Id); err != nil {
|
||||
var l *Ldap
|
||||
var err error
|
||||
if l, err = GetLdap(ldap.Id); err != nil {
|
||||
return false, nil
|
||||
} else if l == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
|
||||
if ldap.Password == "***" {
|
||||
ldap.Password = l.Password
|
||||
}
|
||||
|
||||
affected, err := ormer.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
|
||||
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
@@ -151,7 +157,7 @@ func UpdateLdap(ldap *Ldap) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteLdap(ldap *Ldap) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(ldap.Id).Delete(&Ldap{})
|
||||
affected, err := ormer.Engine.ID(ldap.Id).Delete(&Ldap{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -118,7 +118,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) e
|
||||
// start all autosync goroutine for existing ldap servers in each organizations
|
||||
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error {
|
||||
organizations := []*Organization{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&organizations)
|
||||
err := ormer.Engine.Desc("created_time").Find(&organizations)
|
||||
if err != nil {
|
||||
logs.Info("failed to Star up LdapAutoSynchronizer; ")
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error {
|
||||
}
|
||||
|
||||
func UpdateLdapSyncTime(ldapId string) error {
|
||||
_, err := adapter.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
|
||||
_, err := ormer.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -338,7 +338,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
|
||||
func GetExistUuids(owner string, uuids []string) ([]string, error) {
|
||||
var existUuids []string
|
||||
|
||||
err := adapter.Engine.Table("user").Where("owner = ?", owner).Cols("ldap").
|
||||
err := ormer.Engine.Table("user").Where("owner = ?", owner).Cols("ldap").
|
||||
In("ldap", uuids).Select("DISTINCT ldap").Find(&existUuids)
|
||||
if err != nil {
|
||||
return existUuids, err
|
||||
@@ -350,7 +350,7 @@ func GetExistUuids(owner string, uuids []string) ([]string, error) {
|
||||
func (ldapUser *LdapUser) buildLdapUserName() (string, error) {
|
||||
user := User{}
|
||||
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
||||
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
|
||||
has, err := ormer.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@@ -1,143 +0,0 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Message 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"`
|
||||
|
||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||
Chat string `xorm:"varchar(100) index" json:"chat"`
|
||||
ReplyTo string `xorm:"varchar(100) index" json:"replyTo"`
|
||||
Author string `xorm:"varchar(100)" json:"author"`
|
||||
Text string `xorm:"mediumtext" json:"text"`
|
||||
}
|
||||
|
||||
func GetMaskedMessage(message *Message) *Message {
|
||||
if message == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return message
|
||||
}
|
||||
|
||||
func GetMaskedMessages(messages []*Message) []*Message {
|
||||
for _, message := range messages {
|
||||
message = GetMaskedMessage(message)
|
||||
}
|
||||
return messages
|
||||
}
|
||||
|
||||
func GetMessageCount(owner, organization, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Message{Organization: organization})
|
||||
}
|
||||
|
||||
func GetMessages(owner string) ([]*Message, error) {
|
||||
messages := []*Message{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&messages, &Message{Owner: owner})
|
||||
return messages, err
|
||||
}
|
||||
|
||||
func GetChatMessages(chat string) ([]*Message, error) {
|
||||
messages := []*Message{}
|
||||
err := adapter.Engine.Asc("created_time").Find(&messages, &Message{Chat: chat})
|
||||
return messages, err
|
||||
}
|
||||
|
||||
func GetPaginationMessages(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Message, error) {
|
||||
messages := []*Message{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&messages, &Message{Organization: organization})
|
||||
return messages, err
|
||||
}
|
||||
|
||||
func getMessage(owner string, name string) (*Message, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
message := Message{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &message, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetMessage(id string) (*Message, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getMessage(owner, name)
|
||||
}
|
||||
|
||||
func UpdateMessage(id string, message *Message) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if m, err := getMessage(owner, name); err != nil {
|
||||
return false, err
|
||||
} else if m == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(message)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddMessage(message *Message) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(message)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteMessage(message *Message) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{message.Owner, message.Name}).Delete(&Message{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteChatMessages(chat string) (bool, error) {
|
||||
affected, err := adapter.Engine.Delete(&Message{Chat: chat})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (p *Message) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||
}
|
@@ -43,7 +43,7 @@ func DoMigration() {
|
||||
IDColumnName: "id",
|
||||
}
|
||||
|
||||
m := migrate.New(adapter.Engine, options, migrations)
|
||||
m := migrate.New(ormer.Engine, options, migrations)
|
||||
err := m.Migrate()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@@ -24,9 +24,9 @@ import (
|
||||
type Migrator_1_101_0_PR_1083 struct{}
|
||||
|
||||
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")
|
||||
exist1, _ := ormer.Engine.IsTableExist("model")
|
||||
exist2, _ := ormer.Engine.IsTableExist("permission")
|
||||
exist3, _ := ormer.Engine.IsTableExist("permission_rule")
|
||||
|
||||
if exist1 && exist2 && exist3 {
|
||||
return true
|
||||
|
@@ -23,7 +23,7 @@ import (
|
||||
type Migrator_1_235_0_PR_1530 struct{}
|
||||
|
||||
func (*Migrator_1_235_0_PR_1530) IsMigrationNeeded() bool {
|
||||
exist, _ := adapter.Engine.IsTableExist("casbin_rule")
|
||||
exist, _ := ormer.Engine.IsTableExist("casbin_rule")
|
||||
|
||||
return exist
|
||||
}
|
||||
|
@@ -24,8 +24,8 @@ import (
|
||||
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{})
|
||||
exist, _ := ormer.Engine.IsTableExist("session")
|
||||
err := ormer.Engine.Table("session").Find(&[]*Session{})
|
||||
|
||||
if exist && err != nil {
|
||||
return true
|
||||
|
@@ -22,7 +22,7 @@ import (
|
||||
type Migrator_1_314_0_PR_1841 struct{}
|
||||
|
||||
func (*Migrator_1_314_0_PR_1841) IsMigrationNeeded() bool {
|
||||
count, err := adapter.Engine.Where("password_type=?", "").Count(&User{})
|
||||
count, err := ormer.Engine.Where("password_type=?", "").Count(&User{})
|
||||
if err != nil {
|
||||
// table doesn't exist
|
||||
return false
|
||||
|
@@ -31,6 +31,8 @@ type Model struct {
|
||||
|
||||
ModelText string `xorm:"mediumtext" json:"modelText"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
model.Model `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
func GetModelCount(owner, field, value string) (int64, error) {
|
||||
@@ -40,7 +42,7 @@ func GetModelCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetModels(owner string) ([]*Model, error) {
|
||||
models := []*Model{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&models, &Model{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&models, &Model{Owner: owner})
|
||||
if err != nil {
|
||||
return models, err
|
||||
}
|
||||
@@ -65,7 +67,7 @@ func getModel(owner string, name string) (*Model, error) {
|
||||
}
|
||||
|
||||
m := Model{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&m)
|
||||
existed, err := ormer.Engine.Get(&m)
|
||||
if err != nil {
|
||||
return &m, err
|
||||
}
|
||||
@@ -111,7 +113,7 @@ func UpdateModel(id string, modelObj *Model) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(modelObj)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(modelObj)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -120,7 +122,7 @@ func UpdateModel(id string, modelObj *Model) (bool, error) {
|
||||
}
|
||||
|
||||
func AddModel(model *Model) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(model)
|
||||
affected, err := ormer.Engine.Insert(model)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -129,7 +131,7 @@ func AddModel(model *Model) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteModel(model *Model) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{model.Owner, model.Name}).Delete(&Model{})
|
||||
affected, err := ormer.Engine.ID(core.PK{model.Owner, model.Name}).Delete(&Model{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -137,12 +139,12 @@ func DeleteModel(model *Model) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (model *Model) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", model.Owner, model.Name)
|
||||
func (m *Model) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", m.Owner, m.Name)
|
||||
}
|
||||
|
||||
func modelChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -154,6 +156,15 @@ func modelChangeTrigger(oldName string, newName string) error {
|
||||
permission.Model = newName
|
||||
_, err = session.Where("model=?", oldName).Update(permission)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer := new(Enforcer)
|
||||
enforcer.Model = newName
|
||||
_, err = session.Where("model=?", oldName).Update(enforcer)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -166,3 +177,15 @@ func HasRoleDefinition(m model.Model) bool {
|
||||
}
|
||||
return m["g"] != nil
|
||||
}
|
||||
|
||||
func (m *Model) initModel() error {
|
||||
if m.Model == nil {
|
||||
casbinModel, err := model.NewModelFromString(m.ModelText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Model = casbinModel
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -80,12 +80,12 @@ func GetOrganizationCount(owner, field, value string) (int64, error) {
|
||||
func GetOrganizations(owner string, name ...string) ([]*Organization, error) {
|
||||
organizations := []*Organization{}
|
||||
if name != nil && len(name) > 0 {
|
||||
err := adapter.Engine.Desc("created_time").Where(builder.In("name", name)).Find(&organizations)
|
||||
err := ormer.Engine.Desc("created_time").Where(builder.In("name", name)).Find(&organizations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func GetOrganizations(owner string, name ...string) ([]*Organization, error) {
|
||||
|
||||
func GetOrganizationsByFields(owner string, fields ...string) ([]*Organization, error) {
|
||||
organizations := []*Organization{}
|
||||
err := adapter.Engine.Desc("created_time").Cols(fields...).Find(&organizations, &Organization{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Cols(fields...).Find(&organizations, &Organization{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func getOrganization(owner string, name string) (*Organization, error) {
|
||||
}
|
||||
|
||||
organization := Organization{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&organization)
|
||||
existed, err := ormer.Engine.Get(&organization)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -201,7 +201,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if organization.MasterPassword == "***" {
|
||||
session.Omit("master_password")
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
|
||||
}
|
||||
|
||||
func AddOrganization(organization *Organization) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(organization)
|
||||
affected, err := ormer.Engine.Insert(organization)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -227,7 +227,7 @@ func DeleteOrganization(organization *Organization) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{organization.Owner, organization.Name}).Delete(&Organization{})
|
||||
affected, err := ormer.Engine.ID(core.PK{organization.Owner, organization.Name}).Delete(&Organization{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -299,7 +299,7 @@ func GetDefaultApplication(id string) (*Application, error) {
|
||||
}
|
||||
|
||||
applications := []*Application{}
|
||||
err = adapter.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name})
|
||||
err = ormer.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func GetDefaultApplication(id string) (*Application, error) {
|
||||
}
|
||||
|
||||
func organizationChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -360,7 +360,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
role := new(Role)
|
||||
_, err = adapter.Engine.Where("owner=?", oldName).Get(role)
|
||||
_, err = ormer.Engine.Where("owner=?", oldName).Get(role)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -385,7 +385,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
permission := new(Permission)
|
||||
_, err = adapter.Engine.Where("owner=?", oldName).Get(permission)
|
||||
_, err = ormer.Engine.Where("owner=?", oldName).Get(permission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -409,9 +409,9 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
casbinAdapter := new(CasbinAdapter)
|
||||
casbinAdapter.Owner = newName
|
||||
_, err = session.Where("owner=?", oldName).Update(casbinAdapter)
|
||||
adapter := new(Adapter)
|
||||
adapter.Owner = newName
|
||||
_, err = session.Where("owner=?", oldName).Update(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
payment := new(Payment)
|
||||
payment.Organization = newName
|
||||
payment.Owner = newName
|
||||
_, err = session.Where("organization=?", oldName).Update(payment)
|
||||
if err != nil {
|
||||
return err
|
||||
|
369
object/ormer.go
Normal file
369
object/ormer.go
Normal file
@@ -0,0 +1,369 @@
|
||||
// Copyright 2021 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 (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"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
|
||||
"github.com/xorm-io/core"
|
||||
"github.com/xorm-io/xorm"
|
||||
_ "modernc.org/sqlite" // db = sqlite
|
||||
)
|
||||
|
||||
var ormer *Ormer
|
||||
|
||||
func InitConfig() {
|
||||
err := beego.LoadAppConfig("ini", "../conf/app.conf")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
InitAdapter(true)
|
||||
CreateTables(true)
|
||||
DoMigration()
|
||||
}
|
||||
|
||||
func InitAdapter(createDatabase bool) {
|
||||
if createDatabase {
|
||||
err := createDatabaseForPostgres(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
ormer = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
|
||||
ormer.Engine.SetTableMapper(tbMapper)
|
||||
}
|
||||
|
||||
func CreateTables(createDatabase bool) {
|
||||
if createDatabase {
|
||||
err := ormer.CreateDatabase()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
ormer.createTable()
|
||||
}
|
||||
|
||||
// Ormer represents the MySQL adapter for policy storage.
|
||||
type Ormer struct {
|
||||
driverName string
|
||||
dataSourceName string
|
||||
dbName string
|
||||
Engine *xorm.Engine
|
||||
}
|
||||
|
||||
// finalizer is the destructor for Ormer.
|
||||
func finalizer(a *Ormer) {
|
||||
err := a.Engine.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// NewAdapter is the constructor for Ormer.
|
||||
func NewAdapter(driverName string, dataSourceName string, dbName string) *Ormer {
|
||||
a := &Ormer{}
|
||||
a.driverName = driverName
|
||||
a.dataSourceName = dataSourceName
|
||||
a.dbName = dbName
|
||||
|
||||
// Open the DB, create it if not existed.
|
||||
a.open()
|
||||
|
||||
// Call the destructor when the object is released.
|
||||
runtime.SetFinalizer(a, finalizer)
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
|
||||
if driverName == "postgres" {
|
||||
db, err := sql.Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Ormer) CreateDatabase() error {
|
||||
if a.driverName == "postgres" {
|
||||
return nil
|
||||
}
|
||||
|
||||
engine, err := xorm.NewEngine(a.driverName, a.dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer engine.Close()
|
||||
|
||||
_, err = engine.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s default charset utf8mb4 COLLATE utf8mb4_general_ci", a.dbName))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Ormer) open() {
|
||||
dataSourceName := a.dataSourceName + a.dbName
|
||||
if a.driverName != "mysql" {
|
||||
dataSourceName = a.dataSourceName
|
||||
}
|
||||
|
||||
engine, err := xorm.NewEngine(a.driverName, dataSourceName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
a.Engine = engine
|
||||
}
|
||||
|
||||
func (a *Ormer) close() {
|
||||
_ = a.Engine.Close()
|
||||
a.Engine = nil
|
||||
}
|
||||
|
||||
func (a *Ormer) createTable() {
|
||||
showSql := conf.GetConfigBool("showSql")
|
||||
a.Engine.ShowSQL(showSql)
|
||||
|
||||
err := a.Engine.Sync2(new(Organization))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(User))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Group))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Role))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Permission))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Model))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Adapter))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Enforcer))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Provider))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Application))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Resource))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Token))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(VerificationRecord))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Record))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Webhook))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Syncer))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Cert))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Product))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Payment))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Ldap))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(PermissionRule))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(xormadapter.CasbinRule))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Session))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Subscription))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Plan))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Pricing))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
session = session.And("owner=?", owner)
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
if offset == -1 {
|
||||
session = session.And("owner=?", owner)
|
||||
} else {
|
||||
session = session.And("a.owner=?", owner)
|
||||
}
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
if offset != -1 {
|
||||
field = fmt.Sprintf("a.%s", field)
|
||||
}
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tableName := tableNamePrefix + "user"
|
||||
if offset == -1 {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
} else {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Asc("a." + util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Desc("a." + util.SnakeString(sortField))
|
||||
}
|
||||
}
|
||||
|
||||
return session
|
||||
}
|
@@ -18,6 +18,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
@@ -27,43 +29,44 @@ type Payment struct {
|
||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
|
||||
Provider string `xorm:"varchar(100)" json:"provider"`
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||
User string `xorm:"varchar(100)" json:"user"`
|
||||
ProductName string `xorm:"varchar(100)" json:"productName"`
|
||||
ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"`
|
||||
|
||||
Detail string `xorm:"varchar(255)" json:"detail"`
|
||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
Price float64 `json:"price"`
|
||||
|
||||
PayUrl string `xorm:"varchar(2000)" json:"payUrl"`
|
||||
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
||||
State string `xorm:"varchar(100)" json:"state"`
|
||||
Message string `xorm:"varchar(2000)" json:"message"`
|
||||
|
||||
PersonName string `xorm:"varchar(100)" json:"personName"`
|
||||
PersonIdCard string `xorm:"varchar(100)" json:"personIdCard"`
|
||||
PersonEmail string `xorm:"varchar(100)" json:"personEmail"`
|
||||
PersonPhone string `xorm:"varchar(100)" json:"personPhone"`
|
||||
// Payment Provider Info
|
||||
Provider string `xorm:"varchar(100)" json:"provider"`
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
// Product Info
|
||||
ProductName string `xorm:"varchar(100)" json:"productName"`
|
||||
ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"`
|
||||
Detail string `xorm:"varchar(255)" json:"detail"`
|
||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
Price float64 `json:"price"`
|
||||
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
||||
// Payer Info
|
||||
User string `xorm:"varchar(100)" json:"user"`
|
||||
PersonName string `xorm:"varchar(100)" json:"personName"`
|
||||
PersonIdCard string `xorm:"varchar(100)" json:"personIdCard"`
|
||||
PersonEmail string `xorm:"varchar(100)" json:"personEmail"`
|
||||
PersonPhone string `xorm:"varchar(100)" json:"personPhone"`
|
||||
// Invoice Info
|
||||
InvoiceType string `xorm:"varchar(100)" json:"invoiceType"`
|
||||
InvoiceTitle string `xorm:"varchar(100)" json:"invoiceTitle"`
|
||||
InvoiceTaxId string `xorm:"varchar(100)" json:"invoiceTaxId"`
|
||||
InvoiceRemark string `xorm:"varchar(100)" json:"invoiceRemark"`
|
||||
InvoiceUrl string `xorm:"varchar(255)" json:"invoiceUrl"`
|
||||
// Order Info
|
||||
OutOrderId string `xorm:"varchar(100)" json:"outOrderId"`
|
||||
PayUrl string `xorm:"varchar(2000)" json:"payUrl"`
|
||||
State pp.PaymentState `xorm:"varchar(100)" json:"state"`
|
||||
Message string `xorm:"varchar(2000)" json:"message"`
|
||||
}
|
||||
|
||||
func GetPaymentCount(owner, organization, field, value string) (int64, error) {
|
||||
func GetPaymentCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Payment{Organization: organization})
|
||||
return session.Count(&Payment{Owner: owner})
|
||||
}
|
||||
|
||||
func GetPayments(owner string) ([]*Payment, error) {
|
||||
payments := []*Payment{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -71,9 +74,9 @@ func GetPayments(owner string) ([]*Payment, error) {
|
||||
return payments, nil
|
||||
}
|
||||
|
||||
func GetUserPayments(owner string, organization string, user string) ([]*Payment, error) {
|
||||
func GetUserPayments(owner, user string) ([]*Payment, error) {
|
||||
payments := []*Payment{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner, Organization: organization, User: user})
|
||||
err := ormer.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner, User: user})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -81,10 +84,10 @@ func GetUserPayments(owner string, organization string, user string) ([]*Payment
|
||||
return payments, nil
|
||||
}
|
||||
|
||||
func GetPaginationPayments(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Payment, error) {
|
||||
func GetPaginationPayments(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Payment, error) {
|
||||
payments := []*Payment{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&payments, &Payment{Organization: organization})
|
||||
err := session.Find(&payments, &Payment{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,7 +101,7 @@ func getPayment(owner string, name string) (*Payment, error) {
|
||||
}
|
||||
|
||||
payment := Payment{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&payment)
|
||||
existed, err := ormer.Engine.Get(&payment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -123,16 +126,16 @@ func UpdatePayment(id string, payment *Payment) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddPayment(payment *Payment) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(payment)
|
||||
affected, err := ormer.Engine.Insert(payment)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -141,7 +144,7 @@ func AddPayment(payment *Payment) (bool, error) {
|
||||
}
|
||||
|
||||
func DeletePayment(payment *Payment) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{})
|
||||
affected, err := ormer.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -149,73 +152,72 @@ func DeletePayment(payment *Payment) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func notifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (*Payment, error, string) {
|
||||
provider, err := getProvider(owner, providerName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pProvider, cert, err := provider.getPaymentProvider()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func notifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, *pp.NotifyResult, error) {
|
||||
payment, err := getPayment(owner, paymentName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if payment == nil {
|
||||
err = fmt.Errorf("the payment: %s does not exist", paymentName)
|
||||
return nil, err, pProvider.GetResponseError(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
product, err := getProduct(owner, productName)
|
||||
provider, err := getProvider(owner, payment.Provider)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
pProvider, cert, err := provider.getPaymentProvider()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
product, err := getProduct(owner, payment.ProductName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if product == nil {
|
||||
err = fmt.Errorf("the product: %s does not exist", productName)
|
||||
return payment, err, pProvider.GetResponseError(err)
|
||||
err = fmt.Errorf("the product: %s does not exist", payment.ProductName)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
productDisplayName, paymentName, price, productName, providerName, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
|
||||
if orderId == "" {
|
||||
orderId = payment.OutOrderId
|
||||
}
|
||||
|
||||
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
|
||||
if err != nil {
|
||||
return payment, err, pProvider.GetResponseError(err)
|
||||
return payment, notifyResult, err
|
||||
}
|
||||
|
||||
if productDisplayName != "" && productDisplayName != product.DisplayName {
|
||||
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", productDisplayName, product.DisplayName)
|
||||
return payment, err, pProvider.GetResponseError(err)
|
||||
if notifyResult.ProductDisplayName != "" && notifyResult.ProductDisplayName != product.DisplayName {
|
||||
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", notifyResult.ProductDisplayName, product.DisplayName)
|
||||
return payment, notifyResult, err
|
||||
}
|
||||
|
||||
if price != product.Price {
|
||||
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", price, product.Price)
|
||||
return payment, err, pProvider.GetResponseError(err)
|
||||
if notifyResult.Price != product.Price {
|
||||
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", notifyResult.Price, product.Price)
|
||||
return payment, notifyResult, err
|
||||
}
|
||||
|
||||
err = nil
|
||||
return payment, err, pProvider.GetResponseError(err)
|
||||
return payment, notifyResult, err
|
||||
}
|
||||
|
||||
func NotifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (error, string) {
|
||||
payment, err, errorResponse := notifyPayment(request, body, owner, providerName, productName, paymentName, orderId)
|
||||
func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
|
||||
payment, notifyResult, err := notifyPayment(request, body, owner, paymentName, orderId)
|
||||
if payment != nil {
|
||||
if err != nil {
|
||||
payment.State = "Error"
|
||||
payment.State = pp.PaymentStateError
|
||||
payment.Message = err.Error()
|
||||
} else {
|
||||
payment.State = "Paid"
|
||||
payment.State = notifyResult.PaymentStatus
|
||||
}
|
||||
|
||||
_, err = UpdatePayment(payment.GetId(), payment)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return err, errorResponse
|
||||
return payment, nil
|
||||
}
|
||||
|
||||
func invoicePayment(payment *Payment) (string, error) {
|
||||
@@ -242,7 +244,7 @@ func invoicePayment(payment *Payment) (string, error) {
|
||||
}
|
||||
|
||||
func InvoicePayment(payment *Payment) (string, error) {
|
||||
if payment.State != "Paid" {
|
||||
if payment.State != pp.PaymentStatePaid {
|
||||
return "", fmt.Errorf("the payment state is supposed to be: \"%s\", got: \"%s\"", "Paid", payment.State)
|
||||
}
|
||||
|
||||
|
@@ -74,7 +74,7 @@ func GetPermissionCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetPermissions(owner string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner})
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func getPermission(owner string, name string) (*Permission, error) {
|
||||
}
|
||||
|
||||
permission := Permission{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&permission)
|
||||
existed, err := ormer.Engine.Get(&permission)
|
||||
if err != nil {
|
||||
return &permission, err
|
||||
}
|
||||
@@ -112,13 +112,13 @@ func getPermission(owner string, name string) (*Permission, error) {
|
||||
}
|
||||
|
||||
func GetPermission(id string) (*Permission, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
return getPermission(owner, name)
|
||||
}
|
||||
|
||||
// checkPermissionValid verifies if the permission is valid
|
||||
func checkPermissionValid(permission *Permission) error {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
enforcer.EnableAutoSave(false)
|
||||
|
||||
policies := getPolicies(permission)
|
||||
@@ -149,13 +149,13 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
oldPermission, err := getPermission(owner, name)
|
||||
if oldPermission == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(permission)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(permission)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -164,9 +164,9 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
removeGroupingPolicies(oldPermission)
|
||||
removePolicies(oldPermission)
|
||||
if oldPermission.Adapter != "" && oldPermission.Adapter != permission.Adapter {
|
||||
isEmpty, _ := adapter.Engine.IsTableEmpty(oldPermission.Adapter)
|
||||
isEmpty, _ := ormer.Engine.IsTableEmpty(oldPermission.Adapter)
|
||||
if isEmpty {
|
||||
err = adapter.Engine.DropTables(oldPermission.Adapter)
|
||||
err = ormer.Engine.DropTables(oldPermission.Adapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
}
|
||||
|
||||
func AddPermission(permission *Permission) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(permission)
|
||||
affected, err := ormer.Engine.Insert(permission)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func AddPermissions(permissions []*Permission) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(permissions)
|
||||
affected, err := ormer.Engine.Insert(permissions)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "Duplicate entry") {
|
||||
panic(err)
|
||||
@@ -242,7 +242,7 @@ func AddPermissionsInBatch(permissions []*Permission) bool {
|
||||
}
|
||||
|
||||
func DeletePermission(permission *Permission) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{permission.Owner, permission.Name}).Delete(&Permission{})
|
||||
affected, err := ormer.Engine.ID(core.PK{permission.Owner, permission.Name}).Delete(&Permission{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -251,9 +251,9 @@ func DeletePermission(permission *Permission) (bool, error) {
|
||||
removeGroupingPolicies(permission)
|
||||
removePolicies(permission)
|
||||
if permission.Adapter != "" && permission.Adapter != "permission_rule" {
|
||||
isEmpty, _ := adapter.Engine.IsTableEmpty(permission.Adapter)
|
||||
isEmpty, _ := ormer.Engine.IsTableEmpty(permission.Adapter)
|
||||
if isEmpty {
|
||||
err = adapter.Engine.DropTables(permission.Adapter)
|
||||
err = ormer.Engine.DropTables(permission.Adapter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -266,7 +266,7 @@ func DeletePermission(permission *Permission) (bool, error) {
|
||||
|
||||
func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions)
|
||||
err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -290,7 +290,7 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
|
||||
|
||||
for _, role := range roles {
|
||||
perms := []*Permission{}
|
||||
err := adapter.Engine.Where("roles like ?", "%"+role.Name+"\"%").Find(&perms)
|
||||
err := ormer.Engine.Where("roles like ?", "%"+role.Name+"\"%").Find(&perms)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -310,7 +310,7 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
|
||||
|
||||
func GetPermissionsByRole(roleId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
|
||||
err := ormer.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
@@ -320,7 +320,7 @@ func GetPermissionsByRole(roleId string) ([]*Permission, error) {
|
||||
|
||||
func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
|
||||
err := ormer.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
|
||||
|
||||
func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
||||
err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
@@ -340,7 +340,7 @@ func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, e
|
||||
|
||||
func GetPermissionsByModel(owner string, model string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Model: model})
|
||||
err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Model: model})
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ import (
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
func getEnforcer(p *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||
func getPermissionEnforcer(p *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||
// Init an enforcer instance without specifying a model or adapter.
|
||||
// If you specify an adapter, it will load all policies, which is a
|
||||
// heavy process that can slow down the application.
|
||||
@@ -69,7 +69,7 @@ func getEnforcer(p *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||
func (p *Permission) setEnforcerAdapter(enforcer *casbin.Enforcer) error {
|
||||
tableName := "permission_rule"
|
||||
if len(p.Adapter) != 0 {
|
||||
adapterObj, err := getCasbinAdapter(p.Owner, p.Adapter)
|
||||
adapterObj, err := getAdapter(p.Owner, p.Adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -81,12 +81,12 @@ func (p *Permission) setEnforcerAdapter(enforcer *casbin.Enforcer) error {
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
casbinAdapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer.SetAdapter(casbinAdapter)
|
||||
enforcer.SetAdapter(adapter)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func getGroupingPolicies(permission *Permission) [][]string {
|
||||
}
|
||||
|
||||
func addPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
policies := getPolicies(permission)
|
||||
|
||||
_, err := enforcer.AddPolicies(policies)
|
||||
@@ -214,7 +214,7 @@ func addPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func addGroupingPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
groupingPolicies := getGroupingPolicies(permission)
|
||||
|
||||
if len(groupingPolicies) > 0 {
|
||||
@@ -226,7 +226,7 @@ func addGroupingPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func removeGroupingPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
groupingPolicies := getGroupingPolicies(permission)
|
||||
|
||||
if len(groupingPolicies) > 0 {
|
||||
@@ -238,7 +238,7 @@ func removeGroupingPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func removePolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
policies := getPolicies(permission)
|
||||
|
||||
_, err := enforcer.RemovePolicies(policies)
|
||||
@@ -250,12 +250,12 @@ func removePolicies(permission *Permission) {
|
||||
type CasbinRequest = []interface{}
|
||||
|
||||
func Enforce(permission *Permission, request *CasbinRequest, permissionIds ...string) (bool, error) {
|
||||
enforcer := getEnforcer(permission, permissionIds...)
|
||||
enforcer := getPermissionEnforcer(permission, permissionIds...)
|
||||
return enforcer.Enforce(*request...)
|
||||
}
|
||||
|
||||
func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionIds ...string) ([]bool, error) {
|
||||
enforcer := getEnforcer(permission, permissionIds...)
|
||||
enforcer := getPermissionEnforcer(permission, permissionIds...)
|
||||
return enforcer.BatchEnforce(*requests)
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []
|
||||
|
||||
var values []string
|
||||
for _, permission := range permissions {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
values = append(values, fn(enforcer)...)
|
||||
}
|
||||
return values
|
||||
|
@@ -44,7 +44,7 @@ func GetPlanCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetPlans(owner string) ([]*Plan, error) {
|
||||
plans := []*Plan{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&plans, &Plan{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&plans, &Plan{Owner: owner})
|
||||
if err != nil {
|
||||
return plans, err
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func getPlan(owner, name string) (*Plan, error) {
|
||||
}
|
||||
|
||||
plan := Plan{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&plan)
|
||||
existed, err := ormer.Engine.Get(&plan)
|
||||
if err != nil {
|
||||
return &plan, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func UpdatePlan(id string, plan *Plan) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(plan)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(plan)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -100,7 +100,7 @@ func UpdatePlan(id string, plan *Plan) (bool, error) {
|
||||
}
|
||||
|
||||
func AddPlan(plan *Plan) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(plan)
|
||||
affected, err := ormer.Engine.Insert(plan)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func AddPlan(plan *Plan) (bool, error) {
|
||||
}
|
||||
|
||||
func DeletePlan(plan *Plan) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{plan.Owner, plan.Name}).Delete(plan)
|
||||
affected, err := ormer.Engine.ID(core.PK{plan.Owner, plan.Name}).Delete(plan)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -48,7 +48,7 @@ func GetPricingCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetPricings(owner string) ([]*Pricing, error) {
|
||||
pricings := []*Pricing{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&pricings, &Pricing{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&pricings, &Pricing{Owner: owner})
|
||||
if err != nil {
|
||||
return pricings, err
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func getPricing(owner, name string) (*Pricing, error) {
|
||||
}
|
||||
|
||||
pricing := Pricing{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&pricing)
|
||||
existed, err := ormer.Engine.Get(&pricing)
|
||||
if err != nil {
|
||||
return &pricing, err
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func UpdatePricing(id string, pricing *Pricing) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(pricing)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(pricing)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func UpdatePricing(id string, pricing *Pricing) (bool, error) {
|
||||
}
|
||||
|
||||
func AddPricing(pricing *Pricing) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(pricing)
|
||||
affected, err := ormer.Engine.Insert(pricing)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func AddPricing(pricing *Pricing) (bool, error) {
|
||||
}
|
||||
|
||||
func DeletePricing(pricing *Pricing) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{pricing.Owner, pricing.Name}).Delete(pricing)
|
||||
affected, err := ormer.Engine.ID(core.PK{pricing.Owner, pricing.Name}).Delete(pricing)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -17,6 +17,8 @@ package object
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
@@ -50,7 +52,7 @@ func GetProductCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetProducts(owner string) ([]*Product, error) {
|
||||
products := []*Product{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&products, &Product{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&products, &Product{Owner: owner})
|
||||
if err != nil {
|
||||
return products, err
|
||||
}
|
||||
@@ -75,7 +77,7 @@ func getProduct(owner string, name string) (*Product, error) {
|
||||
}
|
||||
|
||||
product := Product{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&product)
|
||||
existed, err := ormer.Engine.Get(&product)
|
||||
if err != nil {
|
||||
return &product, nil
|
||||
}
|
||||
@@ -100,7 +102,7 @@ func UpdateProduct(id string, product *Product) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(product)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(product)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -109,7 +111,7 @@ func UpdateProduct(id string, product *Product) (bool, error) {
|
||||
}
|
||||
|
||||
func AddProduct(product *Product) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(product)
|
||||
affected, err := ormer.Engine.Insert(product)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -118,7 +120,7 @@ func AddProduct(product *Product) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteProduct(product *Product) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{product.Owner, product.Name}).Delete(&Product{})
|
||||
affected, err := ormer.Engine.ID(core.PK{product.Owner, product.Name}).Delete(&Product{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -183,36 +185,39 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
|
||||
productDisplayName := product.DisplayName
|
||||
|
||||
originFrontend, originBackend := getOriginFromHost(host)
|
||||
returnUrl := fmt.Sprintf("%s/payments/%s/result", originFrontend, paymentName)
|
||||
notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s/%s/%s", originBackend, owner, providerName, productName, paymentName)
|
||||
|
||||
returnUrl := fmt.Sprintf("%s/payments/%s/%s/result", originFrontend, owner, paymentName)
|
||||
notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s", originBackend, owner, paymentName)
|
||||
// Create an Order and get the payUrl
|
||||
payUrl, orderId, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// Create a Payment linked with Product and Order
|
||||
payment := Payment{
|
||||
Owner: product.Owner,
|
||||
Name: paymentName,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: paymentName,
|
||||
Provider: provider.Name,
|
||||
Type: provider.Type,
|
||||
Organization: user.Owner,
|
||||
User: user.Name,
|
||||
Owner: product.Owner,
|
||||
Name: paymentName,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: paymentName,
|
||||
|
||||
Provider: provider.Name,
|
||||
Type: provider.Type,
|
||||
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
Detail: product.Detail,
|
||||
Tag: product.Tag,
|
||||
Currency: product.Currency,
|
||||
Price: product.Price,
|
||||
PayUrl: payUrl,
|
||||
ReturnUrl: product.ReturnUrl,
|
||||
State: "Created",
|
||||
|
||||
User: user.Name,
|
||||
PayUrl: payUrl,
|
||||
State: pp.PaymentStateCreated,
|
||||
OutOrderId: orderId,
|
||||
}
|
||||
|
||||
if provider.Type == "Dummy" {
|
||||
payment.State = "Paid"
|
||||
payment.State = pp.PaymentStatePaid
|
||||
}
|
||||
|
||||
affected, err := AddPayment(&payment)
|
||||
|
@@ -119,7 +119,7 @@ func GetGlobalProviderCount(field, value string) (int64, error) {
|
||||
|
||||
func GetProviders(owner string) ([]*Provider, error) {
|
||||
providers := []*Provider{}
|
||||
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{})
|
||||
err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{})
|
||||
if err != nil {
|
||||
return providers, err
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func GetProviders(owner string) ([]*Provider, error) {
|
||||
|
||||
func GetGlobalProviders() ([]*Provider, error) {
|
||||
providers := []*Provider{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&providers)
|
||||
err := ormer.Engine.Desc("created_time").Find(&providers)
|
||||
if err != nil {
|
||||
return providers, err
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func getProvider(owner string, name string) (*Provider, error) {
|
||||
}
|
||||
|
||||
provider := Provider{Name: name}
|
||||
existed, err := adapter.Engine.Get(&provider)
|
||||
existed, err := ormer.Engine.Get(&provider)
|
||||
if err != nil {
|
||||
return &provider, err
|
||||
}
|
||||
@@ -182,20 +182,6 @@ func GetProvider(id string) (*Provider, error) {
|
||||
return getProvider(owner, name)
|
||||
}
|
||||
|
||||
func getDefaultAiProvider() (*Provider, error) {
|
||||
provider := Provider{Owner: "admin", Category: "AI"}
|
||||
existed, err := adapter.Engine.Get(&provider)
|
||||
if err != nil {
|
||||
return &provider, err
|
||||
}
|
||||
|
||||
if !existed {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &provider, nil
|
||||
}
|
||||
|
||||
func GetWechatMiniProgramProvider(application *Application) *Provider {
|
||||
providers := application.Providers
|
||||
for _, provider := range providers {
|
||||
@@ -221,7 +207,7 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if provider.ClientSecret == "***" {
|
||||
session = session.Omit("client_secret")
|
||||
}
|
||||
@@ -248,7 +234,7 @@ func AddProvider(provider *Provider) (bool, error) {
|
||||
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(provider)
|
||||
affected, err := ormer.Engine.Insert(provider)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -257,7 +243,7 @@ func AddProvider(provider *Provider) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteProvider(provider *Provider) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{provider.Owner, provider.Name}).Delete(&Provider{})
|
||||
affected, err := ormer.Engine.ID(core.PK{provider.Owner, provider.Name}).Delete(&Provider{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -297,7 +283,7 @@ func (p *Provider) GetId() string {
|
||||
func GetCaptchaProviderByOwnerName(applicationId, lang string) (*Provider, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(applicationId)
|
||||
provider := Provider{Owner: owner, Name: name, Category: "Captcha"}
|
||||
existed, err := adapter.Engine.Get(&provider)
|
||||
existed, err := ormer.Engine.Get(&provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -333,7 +319,7 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
|
||||
}
|
||||
|
||||
func providerChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -342,7 +328,7 @@ func providerChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var applications []*Application
|
||||
err = adapter.Engine.Find(&applications)
|
||||
err = ormer.Engine.Find(&applications)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ func AddRecord(record *Record) bool {
|
||||
fmt.Println(errWebhook)
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(record)
|
||||
affected, err := ormer.Engine.Insert(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func GetRecordCount(field, value string, filterRecord *Record) (int64, error) {
|
||||
|
||||
func GetRecords() ([]*Record, error) {
|
||||
records := []*Record{}
|
||||
err := adapter.Engine.Desc("id").Find(&records)
|
||||
err := ormer.Engine.Desc("id").Find(&records)
|
||||
if err != nil {
|
||||
return records, err
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder
|
||||
|
||||
func GetRecordsByField(record *Record) ([]*Record, error) {
|
||||
records := []*Record{}
|
||||
err := adapter.Engine.Find(&records, record)
|
||||
err := ormer.Engine.Find(&records, record)
|
||||
if err != nil {
|
||||
return records, err
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ func GetResources(owner string, user string) ([]*Resource, error) {
|
||||
}
|
||||
|
||||
resources := []*Resource{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner, User: user})
|
||||
err := ormer.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner, User: user})
|
||||
if err != nil {
|
||||
return resources, err
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func getResource(owner string, name string) (*Resource, error) {
|
||||
}
|
||||
|
||||
resource := Resource{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&resource)
|
||||
existed, err := ormer.Engine.Get(&resource)
|
||||
if err != nil {
|
||||
return &resource, err
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func UpdateResource(id string, resource *Resource) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
_, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(resource)
|
||||
_, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(resource)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -117,7 +117,7 @@ func UpdateResource(id string, resource *Resource) (bool, error) {
|
||||
}
|
||||
|
||||
func AddResource(resource *Resource) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(resource)
|
||||
affected, err := ormer.Engine.Insert(resource)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func AddResource(resource *Resource) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteResource(resource *Resource) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{})
|
||||
affected, err := ormer.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ func GetRoleCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetRoles(owner string) ([]*Role, error) {
|
||||
roles := []*Role{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&roles, &Role{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&roles, &Role{Owner: owner})
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
@@ -69,7 +69,7 @@ func getRole(owner string, name string) (*Role, error) {
|
||||
}
|
||||
|
||||
role := Role{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&role)
|
||||
existed, err := ormer.Engine.Get(&role)
|
||||
if err != nil {
|
||||
return &role, err
|
||||
}
|
||||
@@ -82,12 +82,12 @@ func getRole(owner string, name string) (*Role, error) {
|
||||
}
|
||||
|
||||
func GetRole(id string) (*Role, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
return getRole(owner, name)
|
||||
}
|
||||
|
||||
func UpdateRole(id string, role *Role) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
oldRole, err := getRole(owner, name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -137,7 +137,7 @@ func UpdateRole(id string, role *Role) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(role)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(role)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func UpdateRole(id string, role *Role) (bool, error) {
|
||||
}
|
||||
|
||||
func AddRole(role *Role) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(role)
|
||||
affected, err := ormer.Engine.Insert(role)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -190,7 +190,7 @@ func AddRoles(roles []*Role) bool {
|
||||
if len(roles) == 0 {
|
||||
return false
|
||||
}
|
||||
affected, err := adapter.Engine.Insert(roles)
|
||||
affected, err := ormer.Engine.Insert(roles)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "Duplicate entry") {
|
||||
panic(err)
|
||||
@@ -240,7 +240,7 @@ func DeleteRole(role *Role) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{role.Owner, role.Name}).Delete(&Role{})
|
||||
affected, err := ormer.Engine.ID(core.PK{role.Owner, role.Name}).Delete(&Role{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func (role *Role) GetId() string {
|
||||
|
||||
func GetRolesByUser(userId string) ([]*Role, error) {
|
||||
roles := []*Role{}
|
||||
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles)
|
||||
err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles)
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
@@ -278,7 +278,7 @@ func GetRolesByUser(userId string) ([]*Role, error) {
|
||||
}
|
||||
|
||||
func roleChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -287,7 +287,7 @@ func roleChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var roles []*Role
|
||||
err = adapter.Engine.Find(&roles)
|
||||
err = ormer.Engine.Find(&roles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,7 +306,7 @@ func roleChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var permissions []*Permission
|
||||
err = adapter.Engine.Find(&permissions)
|
||||
err = ormer.Engine.Find(&permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func GetMaskedRoles(roles []*Role) []*Role {
|
||||
|
||||
func GetRolesByNamePrefix(owner string, prefix string) ([]*Role, error) {
|
||||
roles := []*Role{}
|
||||
err := adapter.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles)
|
||||
err := ormer.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles)
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
@@ -391,10 +391,13 @@ func GetAncestorRoles(roleIds ...string) ([]*Role, error) {
|
||||
|
||||
// containsRole is a helper function to check if a roles is related to any role in the given list roles
|
||||
func containsRole(role *Role, roleMap map[string]*Role, visited map[string]bool, roleIds ...string) bool {
|
||||
if isContain, ok := visited[role.GetId()]; ok {
|
||||
roleId := role.GetId()
|
||||
if isContain, ok := visited[roleId]; ok {
|
||||
return isContain
|
||||
}
|
||||
|
||||
visited[role.GetId()] = false
|
||||
|
||||
for _, subRole := range role.Roles {
|
||||
if util.HasString(roleIds, subRole) {
|
||||
return true
|
||||
|
@@ -40,9 +40,9 @@ func GetSessions(owner string) ([]*Session, error) {
|
||||
sessions := []*Session{}
|
||||
var err error
|
||||
if owner != "" {
|
||||
err = adapter.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions)
|
||||
err = ormer.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions)
|
||||
} else {
|
||||
err = adapter.Engine.Desc("created_time").Find(&sessions)
|
||||
err = ormer.Engine.Desc("created_time").Find(&sessions)
|
||||
}
|
||||
if err != nil {
|
||||
return sessions, err
|
||||
@@ -70,7 +70,7 @@ func GetSessionCount(owner, field, value string) (int64, error) {
|
||||
func GetSingleSession(id string) (*Session, error) {
|
||||
owner, name, application := util.GetOwnerAndNameAndOtherFromId(id)
|
||||
session := Session{Owner: owner, Name: name, Application: application}
|
||||
get, err := adapter.Engine.Get(&session)
|
||||
get, err := ormer.Engine.Get(&session)
|
||||
if err != nil {
|
||||
return &session, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func UpdateSession(id string, session *Session) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Update(session)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name, application}).Update(session)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func AddSession(session *Session) (bool, error) {
|
||||
if dbSession == nil {
|
||||
session.CreatedTime = util.GetCurrentTime()
|
||||
|
||||
affected, err := adapter.Engine.Insert(session)
|
||||
affected, err := ormer.Engine.Insert(session)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -150,7 +150,7 @@ func DeleteSession(id string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Delete(&Session{})
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name, application}).Delete(&Session{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@ func GetSubscriptionCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetSubscriptions(owner string) ([]*Subscription, error) {
|
||||
subscriptions := []*Subscription{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&subscriptions, &Subscription{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&subscriptions, &Subscription{Owner: owner})
|
||||
if err != nil {
|
||||
return subscriptions, err
|
||||
}
|
||||
@@ -94,7 +94,7 @@ func getSubscription(owner string, name string) (*Subscription, error) {
|
||||
}
|
||||
|
||||
subscription := Subscription{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&subscription)
|
||||
existed, err := ormer.Engine.Get(&subscription)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func UpdateSubscription(id string, subscription *Subscription) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(subscription)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(subscription)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func UpdateSubscription(id string, subscription *Subscription) (bool, error) {
|
||||
}
|
||||
|
||||
func AddSubscription(subscription *Subscription) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(subscription)
|
||||
affected, err := ormer.Engine.Insert(subscription)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -137,7 +137,7 @@ func AddSubscription(subscription *Subscription) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteSubscription(subscription *Subscription) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{subscription.Owner, subscription.Name}).Delete(&Subscription{})
|
||||
affected, err := ormer.Engine.ID(core.PK{subscription.Owner, subscription.Name}).Delete(&Subscription{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ type Syncer struct {
|
||||
IsReadOnly bool `json:"isReadOnly"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
Adapter *Adapter `xorm:"-" json:"-"`
|
||||
Ormer *Ormer `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
func GetSyncerCount(owner, organization, field, value string) (int64, error) {
|
||||
@@ -63,7 +63,7 @@ func GetSyncerCount(owner, organization, field, value string) (int64, error) {
|
||||
|
||||
func GetSyncers(owner string) ([]*Syncer, error) {
|
||||
syncers := []*Syncer{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&syncers, &Syncer{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&syncers, &Syncer{Owner: owner})
|
||||
if err != nil {
|
||||
return syncers, err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func GetSyncers(owner string) ([]*Syncer, error) {
|
||||
|
||||
func GetOrganizationSyncers(owner, organization string) ([]*Syncer, error) {
|
||||
syncers := []*Syncer{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&syncers, &Syncer{Owner: owner, Organization: organization})
|
||||
err := ormer.Engine.Desc("created_time").Find(&syncers, &Syncer{Owner: owner, Organization: organization})
|
||||
if err != nil {
|
||||
return syncers, err
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func getSyncer(owner string, name string) (*Syncer, error) {
|
||||
}
|
||||
|
||||
syncer := Syncer{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&syncer)
|
||||
existed, err := ormer.Engine.Get(&syncer)
|
||||
if err != nil {
|
||||
return &syncer, err
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func UpdateSyncer(id string, syncer *Syncer) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if syncer.Password == "***" {
|
||||
session.Omit("password")
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func updateSyncerErrorText(syncer *Syncer, line string) (bool, error) {
|
||||
|
||||
s.ErrorText = s.ErrorText + line
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{s.Owner, s.Name}).Cols("error_text").Update(s)
|
||||
affected, err := ormer.Engine.ID(core.PK{s.Owner, s.Name}).Cols("error_text").Update(s)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func updateSyncerErrorText(syncer *Syncer, line string) (bool, error) {
|
||||
}
|
||||
|
||||
func AddSyncer(syncer *Syncer) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(syncer)
|
||||
affected, err := ormer.Engine.Insert(syncer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func AddSyncer(syncer *Syncer) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteSyncer(syncer *Syncer) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{syncer.Owner, syncer.Name}).Delete(&Syncer{})
|
||||
affected, err := ormer.Engine.ID(core.PK{syncer.Owner, syncer.Name}).Delete(&Syncer{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ type Affiliation struct {
|
||||
|
||||
func (syncer *Syncer) getAffiliations() ([]*Affiliation, error) {
|
||||
affiliations := []*Affiliation{}
|
||||
err := syncer.Adapter.Engine.Table(syncer.AffiliationTable).Asc("id").Find(&affiliations)
|
||||
err := syncer.Ormer.Engine.Table(syncer.AffiliationTable).Asc("id").Find(&affiliations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ type Credential struct {
|
||||
|
||||
func (syncer *Syncer) getOriginalUsers() ([]*OriginalUser, error) {
|
||||
sql := fmt.Sprintf("select * from %s", syncer.getTable())
|
||||
results, err := syncer.Adapter.Engine.QueryString(sql)
|
||||
results, err := syncer.Ormer.Engine.QueryString(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func (syncer *Syncer) addUser(user *OriginalUser) (bool, error) {
|
||||
keyString, valueString := syncer.getSqlKeyValueStringFromMap(m)
|
||||
|
||||
sql := fmt.Sprintf("insert into %s (%s) values (%s)", syncer.getTable(), keyString, valueString)
|
||||
res, err := syncer.Adapter.Engine.Exec(sql)
|
||||
res, err := syncer.Ormer.Engine.Exec(sql)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (syncer *Syncer) updateUser(user *OriginalUser) (bool, error) {
|
||||
setString := syncer.getSqlSetStringFromMap(m)
|
||||
|
||||
sql := fmt.Sprintf("update %s set %s where %s = %s", syncer.getTable(), setString, syncer.TablePrimaryKey, pkValue)
|
||||
res, err := syncer.Adapter.Engine.Exec(sql)
|
||||
res, err := syncer.Ormer.Engine.Exec(sql)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func (syncer *Syncer) updateUserForOriginalFields(user *User) (bool, error) {
|
||||
|
||||
columns := syncer.getCasdoorColumns()
|
||||
columns = append(columns, "affiliation", "hash", "pre_hash")
|
||||
affected, err := adapter.Engine.ID(core.PK{oldUser.Owner, oldUser.Name}).Cols(columns...).Update(user)
|
||||
affected, err := ormer.Engine.ID(core.PK{oldUser.Owner, oldUser.Name}).Cols(columns...).Update(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (syncer *Syncer) calculateHash(user *OriginalUser) string {
|
||||
}
|
||||
|
||||
func (syncer *Syncer) initAdapter() {
|
||||
if syncer.Adapter == nil {
|
||||
if syncer.Ormer == nil {
|
||||
var dataSourceName string
|
||||
if syncer.DatabaseType == "mssql" {
|
||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
||||
@@ -174,7 +174,7 @@ func (syncer *Syncer) initAdapter() {
|
||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||
}
|
||||
|
||||
syncer.Adapter = NewAdapter(syncer.DatabaseType, dataSourceName, syncer.Database)
|
||||
syncer.Ormer = NewAdapter(syncer.DatabaseType, dataSourceName, syncer.Database)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -196,7 +196,7 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
||||
if syncer.Type == "Keycloak" {
|
||||
// query and set password and password salt from credential table
|
||||
sql := fmt.Sprintf("select * from credential where type = 'password' and user_id = '%s'", originalUser.Id)
|
||||
credentialResult, _ := syncer.Adapter.Engine.QueryString(sql)
|
||||
credentialResult, _ := syncer.Ormer.Engine.QueryString(sql)
|
||||
if len(credentialResult) > 0 {
|
||||
credential := Credential{}
|
||||
_ = json.Unmarshal([]byte(credentialResult[0]["SECRET_DATA"]), &credential)
|
||||
@@ -206,7 +206,7 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
||||
// query and set signup application from user group table
|
||||
sql = fmt.Sprintf("select name from keycloak_group where id = "+
|
||||
"(select group_id as gid from user_group_membership where user_id = '%s')", originalUser.Id)
|
||||
groupResult, _ := syncer.Adapter.Engine.QueryString(sql)
|
||||
groupResult, _ := syncer.Ormer.Engine.QueryString(sql)
|
||||
if len(groupResult) > 0 {
|
||||
originalUser.SignupApplication = groupResult[0]["name"]
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ func GetTokenCount(owner, organization, field, value string) (int64, error) {
|
||||
|
||||
func GetTokens(owner string, organization string) ([]*Token, error) {
|
||||
tokens := []*Token{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&tokens, &Token{Owner: owner, Organization: organization})
|
||||
err := ormer.Engine.Desc("created_time").Find(&tokens, &Token{Owner: owner, Organization: organization})
|
||||
return tokens, err
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func getToken(owner string, name string) (*Token, error) {
|
||||
}
|
||||
|
||||
token := Token{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
existed, err := ormer.Engine.Get(&token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func getToken(owner string, name string) (*Token, error) {
|
||||
|
||||
func getTokenByCode(code string) (*Token, error) {
|
||||
token := Token{Code: code}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
existed, err := ormer.Engine.Get(&token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func getTokenByCode(code string) (*Token, error) {
|
||||
}
|
||||
|
||||
func updateUsedByCode(token *Token) bool {
|
||||
affected, err := adapter.Engine.Where("code=?", token.Code).Cols("code_is_used").Update(token)
|
||||
affected, err := ormer.Engine.Where("code=?", token.Code).Cols("code_is_used").Update(token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -167,7 +167,7 @@ func UpdateToken(id string, token *Token) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(token)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(token)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -176,7 +176,7 @@ func UpdateToken(id string, token *Token) (bool, error) {
|
||||
}
|
||||
|
||||
func AddToken(token *Token) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(token)
|
||||
affected, err := ormer.Engine.Insert(token)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -185,7 +185,7 @@ func AddToken(token *Token) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteToken(token *Token) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{token.Owner, token.Name}).Delete(&Token{})
|
||||
affected, err := ormer.Engine.ID(core.PK{token.Owner, token.Name}).Delete(&Token{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -195,7 +195,7 @@ func DeleteToken(token *Token) (bool, error) {
|
||||
|
||||
func ExpireTokenByAccessToken(accessToken string) (bool, *Application, *Token, error) {
|
||||
token := Token{AccessToken: accessToken}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
existed, err := ormer.Engine.Get(&token)
|
||||
if err != nil {
|
||||
return false, nil, nil, err
|
||||
}
|
||||
@@ -205,7 +205,7 @@ func ExpireTokenByAccessToken(accessToken string) (bool, *Application, *Token, e
|
||||
}
|
||||
|
||||
token.ExpiresIn = 0
|
||||
affected, err := adapter.Engine.ID(core.PK{token.Owner, token.Name}).Cols("expires_in").Update(&token)
|
||||
affected, err := ormer.Engine.ID(core.PK{token.Owner, token.Name}).Cols("expires_in").Update(&token)
|
||||
if err != nil {
|
||||
return false, nil, nil, err
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func ExpireTokenByAccessToken(accessToken string) (bool, *Application, *Token, e
|
||||
func GetTokenByAccessToken(accessToken string) (*Token, error) {
|
||||
// Check if the accessToken is in the database
|
||||
token := Token{AccessToken: accessToken}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
existed, err := ormer.Engine.Get(&token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -235,7 +235,7 @@ func GetTokenByAccessToken(accessToken string) (*Token, error) {
|
||||
|
||||
func GetTokenByTokenAndApplication(token string, application string) (*Token, error) {
|
||||
tokenResult := Token{}
|
||||
existed, err := adapter.Engine.Where("(refresh_token = ? or access_token = ? ) and application = ?", token, token, application).Get(&tokenResult)
|
||||
existed, err := ormer.Engine.Where("(refresh_token = ? or access_token = ? ) and application = ?", token, token, application).Get(&tokenResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -440,7 +440,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
||||
}
|
||||
// check whether the refresh token is valid, and has not expired.
|
||||
token := Token{RefreshToken: refreshToken}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
existed, err := ormer.Engine.Get(&token)
|
||||
if err != nil || !existed {
|
||||
return &TokenError{
|
||||
Error: InvalidGrant,
|
||||
|
@@ -207,7 +207,7 @@ func GetGlobalUserCount(field, value string) (int64, error) {
|
||||
|
||||
func GetGlobalUsers() ([]*User, error) {
|
||||
users := []*User{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&users)
|
||||
err := ormer.Engine.Desc("created_time").Find(&users)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -237,12 +237,12 @@ func GetUserCount(owner, field, value string, groupName string) (int64, error) {
|
||||
}
|
||||
|
||||
func GetOnlineUserCount(owner string, isOnline int) (int64, error) {
|
||||
return adapter.Engine.Where("is_online = ?", isOnline).Count(&User{Owner: owner})
|
||||
return ormer.Engine.Where("is_online = ?", isOnline).Count(&User{Owner: owner})
|
||||
}
|
||||
|
||||
func GetUsers(owner string) ([]*User, error) {
|
||||
users := []*User{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&users, &User{Owner: owner})
|
||||
err := ormer.Engine.Desc("created_time").Find(&users, &User{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -252,7 +252,7 @@ func GetUsers(owner string) ([]*User, error) {
|
||||
|
||||
func GetUsersByTag(owner string, tag string) ([]*User, error) {
|
||||
users := []*User{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&users, &User{Owner: owner, Tag: tag})
|
||||
err := ormer.Engine.Desc("created_time").Find(&users, &User{Owner: owner, Tag: tag})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -262,7 +262,7 @@ func GetUsersByTag(owner string, tag string) ([]*User, error) {
|
||||
|
||||
func GetSortedUsers(owner string, sorter string, limit int) ([]*User, error) {
|
||||
users := []*User{}
|
||||
err := adapter.Engine.Desc(sorter).Limit(limit, 0).Find(&users, &User{Owner: owner})
|
||||
err := ormer.Engine.Desc(sorter).Limit(limit, 0).Find(&users, &User{Owner: owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -291,7 +291,7 @@ func getUser(owner string, name string) (*User, error) {
|
||||
}
|
||||
|
||||
user := User{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -309,7 +309,7 @@ func getUserById(owner string, id string) (*User, error) {
|
||||
}
|
||||
|
||||
user := User{Owner: owner, Id: id}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -326,7 +326,7 @@ func getUserByWechatId(owner string, wechatOpenId string, wechatUnionId string)
|
||||
wechatUnionId = wechatOpenId
|
||||
}
|
||||
user := &User{}
|
||||
existed, err := adapter.Engine.Where("owner = ?", owner).Where("wechat = ? OR wechat = ?", wechatOpenId, wechatUnionId).Get(user)
|
||||
existed, err := ormer.Engine.Where("owner = ?", owner).Where("wechat = ? OR wechat = ?", wechatOpenId, wechatUnionId).Get(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -344,7 +344,7 @@ func GetUserByEmail(owner string, email string) (*User, error) {
|
||||
}
|
||||
|
||||
user := User{Owner: owner, Email: email}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -362,7 +362,7 @@ func GetUserByPhone(owner string, phone string) (*User, error) {
|
||||
}
|
||||
|
||||
user := User{Owner: owner, Phone: phone}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -380,7 +380,7 @@ func GetUserByUserId(owner string, userId string) (*User, error) {
|
||||
}
|
||||
|
||||
user := User{Owner: owner, Id: userId}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -397,7 +397,7 @@ func GetUserByAccessKey(accessKey string) (*User, error) {
|
||||
return nil, nil
|
||||
}
|
||||
user := User{AccessKey: accessKey}
|
||||
existed, err := adapter.Engine.Get(&user)
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -471,7 +471,7 @@ func GetMaskedUsers(users []*User, errs ...error) ([]*User, error) {
|
||||
|
||||
func GetLastUser(owner string) (*User, error) {
|
||||
user := User{Owner: owner}
|
||||
existed, err := adapter.Engine.Desc("created_time", "id").Get(&user)
|
||||
existed, err := ormer.Engine.Desc("created_time", "id").Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -546,7 +546,7 @@ func updateUser(id string, user *User, columns []string) (int64, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols(columns...).Update(user)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).Cols(columns...).Update(user)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -584,7 +584,7 @@ func UpdateUserForAllFields(id string, user *User) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(user)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -638,7 +638,7 @@ func AddUser(user *User) (bool, error) {
|
||||
}
|
||||
user.Ranking = int(count + 1)
|
||||
|
||||
affected, err := adapter.Engine.Insert(user)
|
||||
affected, err := ormer.Engine.Insert(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -670,7 +670,7 @@ func AddUsers(users []*User) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Insert(users)
|
||||
affected, err := ormer.Engine.Insert(users)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "Duplicate entry") {
|
||||
return false, err
|
||||
@@ -715,7 +715,7 @@ func DeleteUser(user *User) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
|
||||
affected, err := ormer.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -779,7 +779,7 @@ func ExtendUserWithRolesAndPermissions(user *User) (err error) {
|
||||
}
|
||||
|
||||
func userChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
session := ormer.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
@@ -788,7 +788,7 @@ func userChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var roles []*Role
|
||||
err = adapter.Engine.Find(&roles)
|
||||
err = ormer.Engine.Find(&roles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -808,7 +808,7 @@ func userChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
var permissions []*Permission
|
||||
err = adapter.Engine.Find(&permissions)
|
||||
err = ormer.Engine.Find(&permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -860,3 +860,11 @@ func AddUserkeys(user *User, isAdmin bool) (bool, error) {
|
||||
|
||||
return UpdateUser(user.GetId(), user, []string{}, isAdmin)
|
||||
}
|
||||
|
||||
func (user *User) IsApplicationAdmin(application *Application) bool {
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return (user.Owner == application.Organization && user.IsAdmin) || user.IsGlobalAdmin
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
func updateUserColumn(column string, user *User) bool {
|
||||
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Cols(column).Update(user)
|
||||
affected, err := ormer.Engine.ID(core.PK{user.Owner, user.Name}).Cols(column).Update(user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ func GetUserByField(organizationName string, field string, value string) (*User,
|
||||
}
|
||||
|
||||
user := User{Owner: organizationName}
|
||||
existed, err := adapter.Engine.Where(fmt.Sprintf("%s=?", strings.ToLower(field)), value).Get(&user)
|
||||
existed, err := ormer.Engine.Where(fmt.Sprintf("%s=?", strings.ToLower(field)), value).Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func SetUserField(user *User, field string, value string) (bool, error) {
|
||||
bean[strings.ToLower(field)] = value
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.Table(user).ID(core.PK{user.Owner, user.Name}).Update(bean)
|
||||
affected, err := ormer.Engine.Table(user).ID(core.PK{user.Owner, user.Name}).Update(bean)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func SetUserField(user *User, field string, value string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
_, err = adapter.Engine.ID(core.PK{user.Owner, user.Name}).Cols("hash").Update(user)
|
||||
_, err = ormer.Engine.ID(core.PK{user.Owner, user.Name}).Cols("hash").Update(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func ClearUserOAuthProperties(user *User, providerType string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Cols("properties").Update(user)
|
||||
affected, err := ormer.Engine.ID(core.PK{user.Owner, user.Name}).Cols("properties").Update(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -66,7 +66,7 @@ func IsAllowSend(user *User, remoteAddr, recordType string) error {
|
||||
if user != nil {
|
||||
record.User = user.GetId()
|
||||
}
|
||||
has, err := adapter.Engine.Desc("created_time").Get(&record)
|
||||
has, err := ormer.Engine.Desc("created_time").Get(&record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,7 +143,7 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
||||
record.Time = time.Now().Unix()
|
||||
record.IsUsed = false
|
||||
|
||||
_, err := adapter.Engine.Insert(record)
|
||||
_, err := ormer.Engine.Insert(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -154,7 +154,7 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
||||
func getVerificationRecord(dest string) (*VerificationRecord, error) {
|
||||
var record VerificationRecord
|
||||
record.Receiver = dest
|
||||
has, err := adapter.Engine.Desc("time").Where("is_used = false").Get(&record)
|
||||
has, err := ormer.Engine.Desc("time").Where("is_used = false").Get(&record)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func DisableVerificationCode(dest string) (err error) {
|
||||
}
|
||||
|
||||
record.IsUsed = true
|
||||
_, err = adapter.Engine.ID(core.PK{record.Owner, record.Name}).AllCols().Update(record)
|
||||
_, err = ormer.Engine.ID(core.PK{record.Owner, record.Name}).AllCols().Update(record)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -49,7 +49,7 @@ func GetWebhookCount(owner, organization, field, value string) (int64, error) {
|
||||
|
||||
func GetWebhooks(owner string, organization string) ([]*Webhook, error) {
|
||||
webhooks := []*Webhook{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&webhooks, &Webhook{Owner: owner, Organization: organization})
|
||||
err := ormer.Engine.Desc("created_time").Find(&webhooks, &Webhook{Owner: owner, Organization: organization})
|
||||
if err != nil {
|
||||
return webhooks, err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func GetPaginationWebhooks(owner, organization string, offset, limit int, field,
|
||||
|
||||
func getWebhooksByOrganization(organization string) ([]*Webhook, error) {
|
||||
webhooks := []*Webhook{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&webhooks, &Webhook{Organization: organization})
|
||||
err := ormer.Engine.Desc("created_time").Find(&webhooks, &Webhook{Organization: organization})
|
||||
if err != nil {
|
||||
return webhooks, err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func getWebhook(owner string, name string) (*Webhook, error) {
|
||||
}
|
||||
|
||||
webhook := Webhook{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&webhook)
|
||||
existed, err := ormer.Engine.Get(&webhook)
|
||||
if err != nil {
|
||||
return &webhook, err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func UpdateWebhook(id string, webhook *Webhook) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(webhook)
|
||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(webhook)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func UpdateWebhook(id string, webhook *Webhook) (bool, error) {
|
||||
}
|
||||
|
||||
func AddWebhook(webhook *Webhook) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(webhook)
|
||||
affected, err := ormer.Engine.Insert(webhook)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func AddWebhook(webhook *Webhook) (bool, error) {
|
||||
}
|
||||
|
||||
func DeleteWebhook(webhook *Webhook) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{webhook.Owner, webhook.Name}).Delete(&Webhook{})
|
||||
affected, err := ormer.Engine.ID(core.PK{webhook.Owner, webhook.Name}).Delete(&Webhook{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
21
pp/alipay.go
21
pp/alipay.go
@@ -16,7 +16,6 @@ package pp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@@ -67,10 +66,10 @@ func (pp *AlipayPaymentProvider) Pay(providerName string, productName string, pa
|
||||
return payUrl, "", nil
|
||||
}
|
||||
|
||||
func (pp *AlipayPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error) {
|
||||
func (pp *AlipayPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
bm, err := alipay.ParseNotifyToBodyMap(request)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
providerName := bm.Get("providerName")
|
||||
@@ -82,13 +81,21 @@ func (pp *AlipayPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
|
||||
ok, err := alipay.VerifySignWithCert(authorityPublicKey, bm)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return "", "", 0, "", "", fmt.Errorf("VerifySignWithCert() failed: %v", ok)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return productDisplayName, paymentName, price, productName, providerName, nil
|
||||
notifyResult := &NotifyResult{
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
Price: price,
|
||||
PaymentName: paymentName,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *AlipayPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
|
@@ -31,8 +31,10 @@ func (pp *DummyPaymentProvider) Pay(providerName string, productName string, pay
|
||||
return payUrl, "", nil
|
||||
}
|
||||
|
||||
func (pp *DummyPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error) {
|
||||
return "", "", 0, "", "", nil
|
||||
func (pp *DummyPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
return &NotifyResult{
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pp *DummyPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
|
22
pp/gc.go
22
pp/gc.go
@@ -216,11 +216,11 @@ func (pp *GcPaymentProvider) Pay(providerName string, productName string, payerN
|
||||
return payRespInfo.PayUrl, "", nil
|
||||
}
|
||||
|
||||
func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error) {
|
||||
func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
reqBody := GcRequestBody{}
|
||||
m, err := url.ParseQuery(string(body))
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqBody.Op = m["op"][0]
|
||||
@@ -232,13 +232,13 @@ func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorit
|
||||
|
||||
notifyReqInfoBytes, err := base64.StdEncoding.DecodeString(reqBody.Data)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var notifyRespInfo GcNotifyRespInfo
|
||||
err = json.Unmarshal(notifyReqInfoBytes, ¬ifyRespInfo)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
providerName := ""
|
||||
@@ -249,10 +249,18 @@ func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorit
|
||||
price := notifyRespInfo.Amount
|
||||
|
||||
if notifyRespInfo.OrderState != "1" {
|
||||
return "", "", 0, "", "", fmt.Errorf("error order state: %s", notifyRespInfo.OrderDate)
|
||||
return nil, fmt.Errorf("error order state: %s", notifyRespInfo.OrderDate)
|
||||
}
|
||||
|
||||
return productDisplayName, paymentName, price, productName, providerName, nil
|
||||
notifyResult := &NotifyResult{
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *GcPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
|
88
pp/paypal.go
88
pp/paypal.go
@@ -20,6 +20,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/paypal"
|
||||
"github.com/go-pay/gopay/pkg/util"
|
||||
@@ -31,8 +33,14 @@ type PaypalPaymentProvider struct {
|
||||
|
||||
func NewPaypalPaymentProvider(clientID string, secret string) (*PaypalPaymentProvider, error) {
|
||||
pp := &PaypalPaymentProvider{}
|
||||
|
||||
client, err := paypal.NewClient(clientID, secret, false)
|
||||
isProd := false
|
||||
if conf.GetConfigString("runmode") == "prod" {
|
||||
isProd = true
|
||||
}
|
||||
client, err := paypal.NewClient(clientID, secret, isProd)
|
||||
//if !isProd {
|
||||
// client.DebugSwitch = gopay.DebugOn
|
||||
//}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -42,27 +50,27 @@ func NewPaypalPaymentProvider(clientID string, secret string) (*PaypalPaymentPro
|
||||
}
|
||||
|
||||
func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (string, string, error) {
|
||||
// pp.Client.DebugSwitch = gopay.DebugOn // Set log to terminal stdout
|
||||
|
||||
// https://github.com/go-pay/gopay/blob/main/doc/paypal.md
|
||||
priceStr := strconv.FormatFloat(price, 'f', 2, 64)
|
||||
var pus []*paypal.PurchaseUnit
|
||||
item := &paypal.PurchaseUnit{
|
||||
units := make([]*paypal.PurchaseUnit, 0, 1)
|
||||
unit := &paypal.PurchaseUnit{
|
||||
ReferenceId: util.GetRandomString(16),
|
||||
Amount: &paypal.Amount{
|
||||
CurrencyCode: currency,
|
||||
Value: priceStr,
|
||||
CurrencyCode: currency, // e.g."USD"
|
||||
Value: priceStr, // e.g."100.00"
|
||||
},
|
||||
Description: joinAttachString([]string{productDisplayName, productName, providerName}),
|
||||
}
|
||||
pus = append(pus, item)
|
||||
units = append(units, unit)
|
||||
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("intent", "CAPTURE")
|
||||
bm.Set("purchase_units", pus)
|
||||
bm.Set("purchase_units", units)
|
||||
bm.SetBodyMap("application_context", func(b gopay.BodyMap) {
|
||||
b.Set("brand_name", "Casdoor")
|
||||
b.Set("locale", "en-PT")
|
||||
b.Set("return_url", returnUrl)
|
||||
b.Set("cancel_url", returnUrl)
|
||||
})
|
||||
|
||||
ppRsp, err := pp.Client.CreateOrder(context.Background(), bm)
|
||||
@@ -72,31 +80,65 @@ func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, pa
|
||||
if ppRsp.Code != paypal.Success {
|
||||
return "", "", errors.New(ppRsp.Error)
|
||||
}
|
||||
|
||||
// {"id":"9BR68863NE220374S","status":"CREATED",
|
||||
// "links":[{"href":"https://api.sandbox.paypal.com/v2/checkout/orders/9BR68863NE220374S","rel":"self","method":"GET"},
|
||||
// {"href":"https://www.sandbox.paypal.com/checkoutnow?token=9BR68863NE220374S","rel":"approve","method":"GET"},
|
||||
// {"href":"https://api.sandbox.paypal.com/v2/checkout/orders/9BR68863NE220374S","rel":"update","method":"PATCH"},
|
||||
// {"href":"https://api.sandbox.paypal.com/v2/checkout/orders/9BR68863NE220374S/capture","rel":"capture","method":"POST"}]}
|
||||
return ppRsp.Response.Links[1].Href, ppRsp.Response.Id, nil
|
||||
}
|
||||
|
||||
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error) {
|
||||
ppRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil)
|
||||
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
captureRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
if ppRsp.Code != paypal.Success {
|
||||
return "", "", 0, "", "", errors.New(ppRsp.Error)
|
||||
if captureRsp.Code != paypal.Success {
|
||||
// If order is already captured, just skip this type of error and check the order detail
|
||||
if !(len(captureRsp.ErrorResponse.Details) == 1 && captureRsp.ErrorResponse.Details[0].Issue == "ORDER_ALREADY_CAPTURED") {
|
||||
return nil, errors.New(captureRsp.ErrorResponse.Message)
|
||||
}
|
||||
}
|
||||
// Check the order detail
|
||||
detailRsp, err := pp.Client.OrderDetail(context.Background(), orderId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if captureRsp.Code != paypal.Success {
|
||||
return nil, errors.New(captureRsp.ErrorResponse.Message)
|
||||
}
|
||||
|
||||
paymentName := ppRsp.Response.Id
|
||||
price, err := strconv.ParseFloat(ppRsp.Response.PurchaseUnits[0].Amount.Value, 64)
|
||||
paymentName := detailRsp.Response.Id
|
||||
price, err := strconv.ParseFloat(detailRsp.Response.PurchaseUnits[0].Amount.Value, 64)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
productDisplayName, productName, providerName, err := parseAttachString(ppRsp.Response.PurchaseUnits[0].Description)
|
||||
currency := detailRsp.Response.PurchaseUnits[0].Amount.CurrencyCode
|
||||
productDisplayName, productName, providerName, err := parseAttachString(detailRsp.Response.PurchaseUnits[0].Description)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
// TODO: status better handler, e.g.`hanging`
|
||||
var paymentStatus PaymentState
|
||||
switch detailRsp.Response.Status { // CREATED、SAVED、APPROVED、VOIDED、COMPLETED、PAYER_ACTION_REQUIRED
|
||||
case "COMPLETED":
|
||||
paymentStatus = PaymentStatePaid
|
||||
default:
|
||||
paymentStatus = PaymentStateError
|
||||
}
|
||||
notifyResult := &NotifyResult{
|
||||
PaymentStatus: paymentStatus,
|
||||
PaymentName: paymentName,
|
||||
|
||||
return productDisplayName, paymentName, price, productName, providerName, nil
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
Price: price,
|
||||
Currency: currency,
|
||||
|
||||
OutOrderId: orderId,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *PaypalPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
|
@@ -14,11 +14,34 @@
|
||||
|
||||
package pp
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type PaymentState string
|
||||
|
||||
const (
|
||||
PaymentStatePaid PaymentState = "Paid"
|
||||
PaymentStateCreated PaymentState = "Created"
|
||||
PaymentStateError PaymentState = "Error"
|
||||
)
|
||||
|
||||
type NotifyResult struct {
|
||||
PaymentName string
|
||||
PaymentStatus PaymentState
|
||||
ProviderName string
|
||||
|
||||
ProductName string
|
||||
ProductDisplayName string
|
||||
Price float64
|
||||
Currency string
|
||||
|
||||
OutOrderId string
|
||||
}
|
||||
|
||||
type PaymentProvider interface {
|
||||
Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (string, string, error)
|
||||
Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error)
|
||||
Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error)
|
||||
GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error)
|
||||
GetResponseError(err error) string
|
||||
}
|
||||
|
@@ -83,22 +83,22 @@ func (pp *WechatPaymentProvider) Pay(providerName string, productName string, pa
|
||||
return wxRsp.Response.CodeUrl, "", nil
|
||||
}
|
||||
|
||||
func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (string, string, float64, string, string, error) {
|
||||
func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
notifyReq, err := wechat.V3ParseNotify(request)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cert := pp.Client.WxPublicKey()
|
||||
err = notifyReq.VerifySignByPK(cert)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiKey := string(pp.Client.ApiV3Key)
|
||||
result, err := notifyReq.DecryptCipherText(apiKey)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paymentName := result.OutTradeNo
|
||||
@@ -106,10 +106,19 @@ func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
|
||||
productDisplayName, productName, providerName, err := parseAttachString(result.Attach)
|
||||
if err != nil {
|
||||
return "", "", 0, "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return productDisplayName, paymentName, price, productName, providerName, nil
|
||||
notifyResult := &NotifyResult{
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *WechatPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
|
@@ -69,7 +69,7 @@ func getObject(ctx *context.Context) (string, string) {
|
||||
// query == "?id=built-in/admin"
|
||||
id := ctx.Input.Query("id")
|
||||
if id != "" {
|
||||
return util.GetOwnerAndNameFromId(id)
|
||||
return util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
}
|
||||
|
||||
owner := ctx.Input.Query("owner")
|
||||
@@ -150,7 +150,7 @@ func getUrlPath(urlPath string) string {
|
||||
return urlPath
|
||||
}
|
||||
|
||||
func AuthzFilter(ctx *context.Context) {
|
||||
func ApiFilter(ctx *context.Context) {
|
||||
subOwner, subName := getSubject(ctx)
|
||||
method := ctx.Request.Method
|
||||
urlPath := getUrlPath(ctx.Request.URL.Path)
|
||||
|
@@ -13,10 +13,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
// Package routers
|
||||
// @APIVersion 1.0.0
|
||||
// @Title Casdoor API
|
||||
// @Description Documentation of Casdoor API
|
||||
// @Contact admin@casbin.org
|
||||
// @APIVersion 1.376.1
|
||||
// @Title Casdoor RESTful API
|
||||
// @Description Swagger Docs of Casdoor Backend API
|
||||
// @Contact casbin@googlegroups.com
|
||||
// @SecurityDefinition AccessToken apiKey Authorization header
|
||||
// @Schemes https,http
|
||||
// @ExternalDocs Find out more about Casdoor
|
||||
// @ExternalDocsUrl https://casdoor.org/
|
||||
package routers
|
||||
|
||||
import (
|
||||
@@ -113,16 +117,22 @@ func initAPI() {
|
||||
beego.Router("/api/add-model", &controllers.ApiController{}, "POST:AddModel")
|
||||
beego.Router("/api/delete-model", &controllers.ApiController{}, "POST:DeleteModel")
|
||||
|
||||
beego.Router("/api/get-adapters", &controllers.ApiController{}, "GET:GetCasbinAdapters")
|
||||
beego.Router("/api/get-adapter", &controllers.ApiController{}, "GET:GetCasbinAdapter")
|
||||
beego.Router("/api/update-adapter", &controllers.ApiController{}, "POST:UpdateCasbinAdapter")
|
||||
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddCasbinAdapter")
|
||||
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteCasbinAdapter")
|
||||
beego.Router("/api/sync-policies", &controllers.ApiController{}, "GET:SyncPolicies")
|
||||
beego.Router("/api/get-adapters", &controllers.ApiController{}, "GET:GetAdapters")
|
||||
beego.Router("/api/get-adapter", &controllers.ApiController{}, "GET:GetAdapter")
|
||||
beego.Router("/api/update-adapter", &controllers.ApiController{}, "POST:UpdateAdapter")
|
||||
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddAdapter")
|
||||
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteAdapter")
|
||||
beego.Router("/api/get-policies", &controllers.ApiController{}, "GET:GetPolicies")
|
||||
beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy")
|
||||
beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
|
||||
beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")
|
||||
|
||||
beego.Router("/api/get-enforcers", &controllers.ApiController{}, "GET:GetEnforcers")
|
||||
beego.Router("/api/get-enforcer", &controllers.ApiController{}, "GET:GetEnforcer")
|
||||
beego.Router("/api/update-enforcer", &controllers.ApiController{}, "POST:UpdateEnforcer")
|
||||
beego.Router("/api/add-enforcer", &controllers.ApiController{}, "POST:AddEnforcer")
|
||||
beego.Router("/api/delete-enforcer", &controllers.ApiController{}, "POST:DeleteEnforcer")
|
||||
|
||||
beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword")
|
||||
beego.Router("/api/check-user-password", &controllers.ApiController{}, "POST:CheckUserPassword")
|
||||
beego.Router("/api/get-email-and-phone", &controllers.ApiController{}, "GET:GetEmailAndPhone")
|
||||
@@ -201,19 +211,6 @@ func initAPI() {
|
||||
beego.Router("/api/add-cert", &controllers.ApiController{}, "POST:AddCert")
|
||||
beego.Router("/api/delete-cert", &controllers.ApiController{}, "POST:DeleteCert")
|
||||
|
||||
beego.Router("/api/get-chats", &controllers.ApiController{}, "GET:GetChats")
|
||||
beego.Router("/api/get-chat", &controllers.ApiController{}, "GET:GetChat")
|
||||
beego.Router("/api/update-chat", &controllers.ApiController{}, "POST:UpdateChat")
|
||||
beego.Router("/api/add-chat", &controllers.ApiController{}, "POST:AddChat")
|
||||
beego.Router("/api/delete-chat", &controllers.ApiController{}, "POST:DeleteChat")
|
||||
|
||||
beego.Router("/api/get-messages", &controllers.ApiController{}, "GET:GetMessages")
|
||||
beego.Router("/api/get-message", &controllers.ApiController{}, "GET:GetMessage")
|
||||
beego.Router("/api/get-message-answer", &controllers.ApiController{}, "GET:GetMessageAnswer")
|
||||
beego.Router("/api/update-message", &controllers.ApiController{}, "POST:UpdateMessage")
|
||||
beego.Router("/api/add-message", &controllers.ApiController{}, "POST:AddMessage")
|
||||
beego.Router("/api/delete-message", &controllers.ApiController{}, "POST:DeleteMessage")
|
||||
|
||||
beego.Router("/api/get-subscriptions", &controllers.ApiController{}, "GET:GetSubscriptions")
|
||||
beego.Router("/api/get-subscription", &controllers.ApiController{}, "GET:GetSubscription")
|
||||
beego.Router("/api/update-subscription", &controllers.ApiController{}, "POST:UpdateSubscription")
|
||||
@@ -245,24 +242,12 @@ func initAPI() {
|
||||
beego.Router("/api/update-payment", &controllers.ApiController{}, "POST:UpdatePayment")
|
||||
beego.Router("/api/add-payment", &controllers.ApiController{}, "POST:AddPayment")
|
||||
beego.Router("/api/delete-payment", &controllers.ApiController{}, "POST:DeletePayment")
|
||||
beego.Router("/api/notify-payment/?:owner/?:provider/?:product/?:payment", &controllers.ApiController{}, "POST:NotifyPayment")
|
||||
beego.Router("/api/notify-payment/?:owner/?:payment", &controllers.ApiController{}, "POST:NotifyPayment")
|
||||
beego.Router("/api/invoice-payment", &controllers.ApiController{}, "POST:InvoicePayment")
|
||||
|
||||
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
|
||||
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
|
||||
|
||||
beego.Router("/.well-known/openid-configuration", &controllers.RootController{}, "GET:GetOidcDiscovery")
|
||||
beego.Router("/.well-known/jwks", &controllers.RootController{}, "*:GetJwks")
|
||||
|
||||
beego.Router("/cas/:organization/:application/serviceValidate", &controllers.RootController{}, "GET:CasServiceValidate")
|
||||
beego.Router("/cas/:organization/:application/proxyValidate", &controllers.RootController{}, "GET:CasProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/proxy", &controllers.RootController{}, "GET:CasProxy")
|
||||
beego.Router("/cas/:organization/:application/validate", &controllers.RootController{}, "GET:CasValidate")
|
||||
|
||||
beego.Router("/cas/:organization/:application/p3/serviceValidate", &controllers.RootController{}, "GET:CasP3ServiceAndProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/p3/proxyValidate", &controllers.RootController{}, "GET:CasP3ServiceAndProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/samlValidate", &controllers.RootController{}, "POST:SamlValidate")
|
||||
|
||||
beego.Router("/api/webauthn/signup/begin", &controllers.ApiController{}, "Get:WebAuthnSignupBegin")
|
||||
beego.Router("/api/webauthn/signup/finish", &controllers.ApiController{}, "Post:WebAuthnSignupFinish")
|
||||
beego.Router("/api/webauthn/signin/begin", &controllers.ApiController{}, "Get:WebAuthnSigninBegin")
|
||||
@@ -280,4 +265,16 @@ func initAPI() {
|
||||
beego.Router("/api/get-prometheus-info", &controllers.ApiController{}, "GET:GetPrometheusInfo")
|
||||
|
||||
beego.Handler("/api/metrics", promhttp.Handler())
|
||||
|
||||
beego.Router("/.well-known/openid-configuration", &controllers.RootController{}, "GET:GetOidcDiscovery")
|
||||
beego.Router("/.well-known/jwks", &controllers.RootController{}, "*:GetJwks")
|
||||
|
||||
beego.Router("/cas/:organization/:application/serviceValidate", &controllers.RootController{}, "GET:CasServiceValidate")
|
||||
beego.Router("/cas/:organization/:application/proxyValidate", &controllers.RootController{}, "GET:CasProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/proxy", &controllers.RootController{}, "GET:CasProxy")
|
||||
beego.Router("/cas/:organization/:application/validate", &controllers.RootController{}, "GET:CasValidate")
|
||||
|
||||
beego.Router("/cas/:organization/:application/p3/serviceValidate", &controllers.RootController{}, "GET:CasP3ServiceAndProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/p3/proxyValidate", &controllers.RootController{}, "GET:CasP3ServiceAndProxyValidate")
|
||||
beego.Router("/cas/:organization/:application/samlValidate", &controllers.RootController{}, "POST:SamlValidate")
|
||||
}
|
||||
|
@@ -64,15 +64,18 @@ func StaticFilter(ctx *context.Context) {
|
||||
if !util.FileExist(path) {
|
||||
path = "web/build/index.html"
|
||||
}
|
||||
if !util.FileExist(path) {
|
||||
return
|
||||
}
|
||||
|
||||
if oldStaticBaseUrl == newStaticBaseUrl {
|
||||
makeGzipResponse(ctx.ResponseWriter, ctx.Request, path)
|
||||
} else {
|
||||
serveFileWithReplace(ctx.ResponseWriter, ctx.Request, path, oldStaticBaseUrl, newStaticBaseUrl)
|
||||
serveFileWithReplace(ctx.ResponseWriter, ctx.Request, path)
|
||||
}
|
||||
}
|
||||
|
||||
func serveFileWithReplace(w http.ResponseWriter, r *http.Request, name string, old string, new string) {
|
||||
func serveFileWithReplace(w http.ResponseWriter, r *http.Request, name string) {
|
||||
f, err := os.Open(filepath.Clean(name))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -85,13 +88,9 @@ func serveFileWithReplace(w http.ResponseWriter, r *http.Request, name string, o
|
||||
}
|
||||
|
||||
oldContent := util.ReadStringFromPath(name)
|
||||
newContent := strings.ReplaceAll(oldContent, old, new)
|
||||
newContent := strings.ReplaceAll(oldContent, oldStaticBaseUrl, newStaticBaseUrl)
|
||||
|
||||
http.ServeContent(w, r, d.Name(), d.ModTime(), strings.NewReader(newContent))
|
||||
_, err = w.Write([]byte(newContent))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type gzipResponseWriter struct {
|
||||
@@ -105,12 +104,12 @@ func (w gzipResponseWriter) Write(b []byte) (int, error) {
|
||||
|
||||
func makeGzipResponse(w http.ResponseWriter, r *http.Request, path string) {
|
||||
if !enableGzip || !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
http.ServeFile(w, r, path)
|
||||
serveFileWithReplace(w, r, path)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
gz := gzip.NewWriter(w)
|
||||
defer gz.Close()
|
||||
gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
|
||||
http.ServeFile(gzw, r, path)
|
||||
serveFileWithReplace(gzw, r, path)
|
||||
}
|
||||
|
@@ -1,14 +1,18 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Casdoor API",
|
||||
"description": "Documentation of Casdoor API",
|
||||
"version": "1.0.0",
|
||||
"title": "Casdoor RESTful API",
|
||||
"description": "Swagger Docs of Casdoor Backend API",
|
||||
"version": "1.376.1",
|
||||
"contact": {
|
||||
"email": "admin@casbin.org"
|
||||
"email": "casbin@googlegroups.com"
|
||||
}
|
||||
},
|
||||
"basePath": "/",
|
||||
"schemes": [
|
||||
"https",
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/.well-known/jwks": {
|
||||
"get": {
|
||||
@@ -49,7 +53,7 @@
|
||||
"Adapter API"
|
||||
],
|
||||
"description": "add adapter",
|
||||
"operationId": "ApiController.AddCasbinAdapter",
|
||||
"operationId": "ApiController.AddAdapter",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
@@ -155,6 +159,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "add enforcer",
|
||||
"operationId": "ApiController.AddEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "enforcer",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -967,7 +999,7 @@
|
||||
"Adapter API"
|
||||
],
|
||||
"description": "delete adapter",
|
||||
"operationId": "ApiController.DeleteCasbinAdapter",
|
||||
"operationId": "ApiController.DeleteAdapter",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
@@ -1073,6 +1105,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "delete enforcer",
|
||||
"operationId": "ApiController.DeleteEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Enforce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1691,7 +1751,7 @@
|
||||
"Adapter API"
|
||||
],
|
||||
"description": "get adapter",
|
||||
"operationId": "ApiController.GetCasbinAdapter",
|
||||
"operationId": "ApiController.GetAdapter",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
@@ -1717,7 +1777,7 @@
|
||||
"Adapter API"
|
||||
],
|
||||
"description": "get adapters",
|
||||
"operationId": "ApiController.GetCasbinAdapters",
|
||||
"operationId": "ApiController.GetAdapters",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
@@ -2018,6 +2078,61 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-enforcer": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "get enforcer",
|
||||
"operationId": "ApiController.GetEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of enforcer",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-enforcers": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "get enforcers",
|
||||
"operationId": "ApiController.GetEnforcers",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of enforcers",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Enforcer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-global-providers": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3571,7 +3686,8 @@
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the webhook",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3597,7 +3713,8 @@
|
||||
"name": "owner",
|
||||
"description": "The owner of webhooks",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3610,7 +3727,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"test_apiKey": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/health": {
|
||||
@@ -4260,7 +4382,7 @@
|
||||
"Adapter API"
|
||||
],
|
||||
"description": "update adapter",
|
||||
"operationId": "ApiController.UpdateCasbinAdapter",
|
||||
"operationId": "ApiController.UpdateAdapter",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
@@ -4394,6 +4516,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "update enforcer",
|
||||
"operationId": "ApiController.UpdateEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of enforcer",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "enforcer",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -5024,7 +5181,8 @@
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the webhook",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
@@ -5289,6 +5447,10 @@
|
||||
"title": "Response",
|
||||
"type": "object"
|
||||
},
|
||||
"casbin.Enforcer": {
|
||||
"title": "Enforcer",
|
||||
"type": "object"
|
||||
},
|
||||
"controllers.AuthForm": {
|
||||
"title": "AuthForm",
|
||||
"type": "object"
|
||||
@@ -5662,6 +5824,43 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Enforce": {
|
||||
"title": "Enforce",
|
||||
"type": "object"
|
||||
},
|
||||
"object.Enforcer": {
|
||||
"title": "Enforcer",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"adapter": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTime": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.GaugeVecInfo": {
|
||||
"title": "GaugeVecInfo",
|
||||
"type": "object",
|
||||
@@ -7323,6 +7522,9 @@
|
||||
"meetup": {
|
||||
"type": "string"
|
||||
},
|
||||
"metamask": {
|
||||
"type": "string"
|
||||
},
|
||||
"mfaEmailEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -7670,5 +7872,16 @@
|
||||
"title": "Engine",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"AccessToken": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
"description": "Find out more about Casdoor",
|
||||
"url": "https://casdoor.org/"
|
||||
}
|
||||
}
|
@@ -1,11 +1,14 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: Casdoor API
|
||||
description: Documentation of Casdoor API
|
||||
version: 1.0.0
|
||||
title: Casdoor RESTful API
|
||||
description: Swagger Docs of Casdoor Backend API
|
||||
version: 1.376.1
|
||||
contact:
|
||||
email: admin@casbin.org
|
||||
email: casbin@googlegroups.com
|
||||
basePath: /
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
paths:
|
||||
/.well-known/jwks:
|
||||
get:
|
||||
@@ -33,7 +36,7 @@ paths:
|
||||
tags:
|
||||
- Adapter API
|
||||
description: add adapter
|
||||
operationId: ApiController.AddCasbinAdapter
|
||||
operationId: ApiController.AddAdapter
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
@@ -100,6 +103,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: add enforcer
|
||||
operationId: ApiController.AddEnforcer
|
||||
parameters:
|
||||
- in: body
|
||||
name: enforcer
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/add-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -626,7 +647,7 @@ paths:
|
||||
tags:
|
||||
- Adapter API
|
||||
description: delete adapter
|
||||
operationId: ApiController.DeleteCasbinAdapter
|
||||
operationId: ApiController.DeleteAdapter
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
@@ -693,6 +714,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: delete enforcer
|
||||
operationId: ApiController.DeleteEnforcer
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Enforce'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/delete-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -1092,7 +1131,7 @@ paths:
|
||||
tags:
|
||||
- Adapter API
|
||||
description: get adapter
|
||||
operationId: ApiController.GetCasbinAdapter
|
||||
operationId: ApiController.GetAdapter
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
@@ -1109,7 +1148,7 @@ paths:
|
||||
tags:
|
||||
- Adapter API
|
||||
description: get adapters
|
||||
operationId: ApiController.GetCasbinAdapters
|
||||
operationId: ApiController.GetAdapters
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
@@ -1307,6 +1346,42 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/get-enforcer:
|
||||
get:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: get enforcer
|
||||
operationId: ApiController.GetEnforcer
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of enforcer
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/get-enforcers:
|
||||
get:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: get enforcers
|
||||
operationId: ApiController.GetEnforcers
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of enforcers
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Enforcer'
|
||||
/api/get-global-providers:
|
||||
get:
|
||||
tags:
|
||||
@@ -2329,6 +2404,7 @@ paths:
|
||||
description: The id ( owner/name ) of the webhook
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
@@ -2346,6 +2422,7 @@ paths:
|
||||
description: The owner of webhooks
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
@@ -2353,6 +2430,8 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Webhook'
|
||||
security:
|
||||
- test_apiKey: []
|
||||
/api/health:
|
||||
get:
|
||||
tags:
|
||||
@@ -2782,7 +2861,7 @@ paths:
|
||||
tags:
|
||||
- Adapter API
|
||||
description: update adapter
|
||||
operationId: ApiController.UpdateCasbinAdapter
|
||||
operationId: ApiController.UpdateAdapter
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
@@ -2869,6 +2948,29 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: update enforcer
|
||||
operationId: ApiController.UpdateEnforcer
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of enforcer
|
||||
required: true
|
||||
type: string
|
||||
- in: body
|
||||
name: enforcer
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/update-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -3286,6 +3388,7 @@ paths:
|
||||
description: The id ( owner/name ) of the webhook
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the webhook
|
||||
@@ -3458,6 +3561,9 @@ definitions:
|
||||
Response:
|
||||
title: Response
|
||||
type: object
|
||||
casbin.Enforcer:
|
||||
title: Enforcer
|
||||
type: object
|
||||
controllers.AuthForm:
|
||||
title: AuthForm
|
||||
type: object
|
||||
@@ -3710,6 +3816,31 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
object.Enforce:
|
||||
title: Enforce
|
||||
type: object
|
||||
object.Enforcer:
|
||||
title: Enforcer
|
||||
type: object
|
||||
properties:
|
||||
adapter:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
isEnabled:
|
||||
type: boolean
|
||||
model:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
updatedTime:
|
||||
type: string
|
||||
object.GaugeVecInfo:
|
||||
title: GaugeVecInfo
|
||||
type: object
|
||||
@@ -4828,6 +4959,8 @@ definitions:
|
||||
$ref: '#/definitions/object.ManagedAccount'
|
||||
meetup:
|
||||
type: string
|
||||
metamask:
|
||||
type: string
|
||||
mfaEmailEnabled:
|
||||
type: boolean
|
||||
mfaPhoneEnabled:
|
||||
@@ -5062,3 +5195,11 @@ definitions:
|
||||
xorm.Engine:
|
||||
title: Engine
|
||||
type: object
|
||||
securityDefinitions:
|
||||
AccessToken:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
externalDocs:
|
||||
description: Find out more about Casdoor
|
||||
url: https://casdoor.org/
|
||||
|
@@ -33,6 +33,7 @@
|
||||
"react-device-detect": "^2.2.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-github-corner": "^2.5.0",
|
||||
"react-google-one-tap-login": "^0.1.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-highlight-words": "^0.18.0",
|
||||
"react-i18next": "^11.8.7",
|
||||
|
@@ -13,14 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import PolicyTable from "./table/PoliciyTable";
|
||||
require("codemirror/theme/material-darker.css");
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
@@ -36,7 +35,6 @@ class AdapterEditPage extends React.Component {
|
||||
adapterName: props.match.params.adapterName,
|
||||
adapter: null,
|
||||
organizations: [],
|
||||
models: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
}
|
||||
@@ -58,8 +56,6 @@ class AdapterEditPage extends React.Component {
|
||||
this.setState({
|
||||
adapter: res.data,
|
||||
});
|
||||
|
||||
this.getModels(this.state.organizationName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -73,24 +69,10 @@ class AdapterEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getModels(organizationName) {
|
||||
ModelBackend.getModels(organizationName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
models: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseAdapterField(key, value) {
|
||||
if (["port"].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -104,61 +86,12 @@ class AdapterEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
renderAdapter() {
|
||||
renderDataSourceNameConfig() {
|
||||
if (Setting.builtInObject(this.state.adapter)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("adapter:New Adapter") : i18next.t("adapter:Edit Adapter")}
|
||||
<Button onClick={() => this.submitAdapterEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitAdapterEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteAdapter()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.adapter.owner} onChange={(value => {
|
||||
this.getModels(value);
|
||||
this.updateAdapterField("owner", value);
|
||||
})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.adapter.name} onChange={e => {
|
||||
this.updateAdapterField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.type} onChange={(value => {
|
||||
this.updateAdapterField("type", value);
|
||||
const adapter = this.state.adapter;
|
||||
// adapter["tableColumns"] = Setting.getAdapterTableColumns(this.state.adapter);
|
||||
this.setState({
|
||||
adapter: adapter,
|
||||
});
|
||||
})}>
|
||||
{
|
||||
["Database"]
|
||||
.map((item, index) => <Option key={index} value={item}>{item}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Host"), i18next.t("provider:Host - Tooltip"))} :
|
||||
@@ -174,8 +107,8 @@ class AdapterEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("provider:Port"), i18next.t("provider:Port - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<InputNumber value={this.state.adapter.port} onChange={value => {
|
||||
this.updateAdapterField("port", value);
|
||||
<Input value={this.state.adapter.port} onChange={e => {
|
||||
this.updateAdapterField("port", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -199,12 +132,70 @@ class AdapterEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderAdapter() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("adapter:New Adapter") : i18next.t("adapter:Edit Adapter")}
|
||||
<Button onClick={() => this.submitAdapterEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitAdapterEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteAdapter()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account) || Setting.builtInObject(this.state.adapter)} value={this.state.adapter.owner} onChange={(value => {
|
||||
this.updateAdapterField("owner", value);
|
||||
})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input disabled={Setting.builtInObject(this.state.adapter)} value={this.state.adapter.name} onChange={e => {
|
||||
this.updateAdapterField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.adapter)} style={{width: "100%"}} value={this.state.adapter.type} onChange={(value => {
|
||||
this.updateAdapterField("type", value);
|
||||
const adapter = this.state.adapter;
|
||||
// adapter["tableColumns"] = Setting.getAdapterTableColumns(this.state.adapter);
|
||||
this.setState({
|
||||
adapter: adapter,
|
||||
});
|
||||
})}>
|
||||
{
|
||||
["Database"]
|
||||
.map((item, index) => <Option key={index} value={item}>{item}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("syncer:Database type"), i18next.t("syncer:Database type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.databaseType} onChange={(value => {this.updateAdapterField("databaseType", value);})}>
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.adapter)} style={{width: "100%"}} value={this.state.adapter.databaseType} onChange={(value => {this.updateAdapterField("databaseType", value);})}>
|
||||
{
|
||||
[
|
||||
{id: "mysql", name: "MySQL"},
|
||||
@@ -217,12 +208,13 @@ class AdapterEditPage extends React.Component {
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
{this.state.adapter.type === "Database" ? this.renderDataSourceNameConfig() : null}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("syncer:Database"), i18next.t("syncer:Database - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.adapter.database} onChange={e => {
|
||||
<Input disabled={Setting.builtInObject(this.state.adapter)} value={this.state.adapter.database} onChange={e => {
|
||||
this.updateAdapterField("database", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
@@ -233,25 +225,11 @@ class AdapterEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.adapter.table}
|
||||
disabled={this.state.adapter.type === "Keycloak"} onChange={e => {
|
||||
disabled={Setting.builtInObject(this.state.adapter)} onChange={e => {
|
||||
this.updateAdapterField("table", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Model"), i18next.t("general:Model - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.model} onChange={(model => {
|
||||
this.updateAdapterField("model", model);
|
||||
})}>
|
||||
{
|
||||
this.state.models.map((model, index) => <Option key={index} value={model.name}>{model.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
|
||||
|
@@ -32,7 +32,7 @@ class AdapterListPage extends BaseListPage {
|
||||
createdTime: moment().format(),
|
||||
type: "Database",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
port: "3306",
|
||||
user: "root",
|
||||
password: "123456",
|
||||
databaseType: "mysql",
|
||||
@@ -206,6 +206,7 @@ class AdapterListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/adapters/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
disabled={Setting.builtInObject(record)}
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteAdapter(index)}
|
||||
>
|
||||
|
@@ -15,14 +15,10 @@
|
||||
import React, {Component} from "react";
|
||||
import "./App.less";
|
||||
import {Helmet} from "react-helmet";
|
||||
import EnableMfaNotification from "./common/notifaction/EnableMfaNotification";
|
||||
import GroupTreePage from "./GroupTreePage";
|
||||
import GroupEditPage from "./GroupEdit";
|
||||
import GroupListPage from "./GroupList";
|
||||
import {MfaRuleRequired} from "./Setting";
|
||||
import * as Setting from "./Setting";
|
||||
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
||||
import {BarsOutlined, CommentOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||
import {BarsOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||
import {Alert, Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result} from "antd";
|
||||
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
||||
import OrganizationListPage from "./OrganizationListPage";
|
||||
@@ -33,6 +29,11 @@ import RoleListPage from "./RoleListPage";
|
||||
import RoleEditPage from "./RoleEditPage";
|
||||
import PermissionListPage from "./PermissionListPage";
|
||||
import PermissionEditPage from "./PermissionEditPage";
|
||||
import EnforcerEditPage from "./EnforcerEditPage";
|
||||
import EnforcerListPage from "./EnforcerListPage";
|
||||
import GroupTreePage from "./GroupTreePage";
|
||||
import GroupEditPage from "./GroupEdit";
|
||||
import GroupListPage from "./GroupList";
|
||||
import ProviderListPage from "./ProviderListPage";
|
||||
import ProviderEditPage from "./ProviderEditPage";
|
||||
import ApplicationListPage from "./ApplicationListPage";
|
||||
@@ -55,11 +56,6 @@ import PricingListPage from "./PricingListPage";
|
||||
import PricingEditPage from "./PricingEditPage";
|
||||
import PlanListPage from "./PlanListPage";
|
||||
import PlanEditPage from "./PlanEditPage";
|
||||
import ChatListPage from "./ChatListPage";
|
||||
import ChatEditPage from "./ChatEditPage";
|
||||
import ChatPage from "./ChatPage";
|
||||
import MessageEditPage from "./MessageEditPage";
|
||||
import MessageListPage from "./MessageListPage";
|
||||
import ProductListPage from "./ProductListPage";
|
||||
import ProductEditPage from "./ProductEditPage";
|
||||
import ProductBuyPage from "./ProductBuyPage";
|
||||
@@ -86,6 +82,7 @@ import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||
import SamlCallback from "./auth/SamlCallback";
|
||||
import i18next from "i18next";
|
||||
import {withTranslation} from "react-i18next";
|
||||
import EnableMfaNotification from "./common/notifaction/EnableMfaNotification";
|
||||
import LanguageSelect from "./common/select/LanguageSelect";
|
||||
import ThemeSelect from "./common/select/ThemeSelect";
|
||||
import OrganizationSelect from "./common/select/OrganizationSelect";
|
||||
@@ -164,6 +161,8 @@ class App extends Component {
|
||||
this.setState({selectedMenuKey: "/models"});
|
||||
} else if (uri.includes("/adapters")) {
|
||||
this.setState({selectedMenuKey: "/adapters"});
|
||||
} else if (uri.includes("/enforcers")) {
|
||||
this.setState({selectedMenuKey: "/enforcers"});
|
||||
} else if (uri.includes("/providers")) {
|
||||
this.setState({selectedMenuKey: "/providers"});
|
||||
} else if (uri.includes("/applications")) {
|
||||
@@ -182,10 +181,6 @@ class App extends Component {
|
||||
this.setState({selectedMenuKey: "/syncers"});
|
||||
} else if (uri.includes("/certs")) {
|
||||
this.setState({selectedMenuKey: "/certs"});
|
||||
} else if (uri.includes("/chats")) {
|
||||
this.setState({selectedMenuKey: "/chats"});
|
||||
} else if (uri.includes("/messages")) {
|
||||
this.setState({selectedMenuKey: "/messages"});
|
||||
} else if (uri.includes("/products")) {
|
||||
this.setState({selectedMenuKey: "/products"});
|
||||
} else if (uri.includes("/payments")) {
|
||||
@@ -364,11 +359,6 @@ class App extends Component {
|
||||
items.push(Setting.getItem(<><SettingOutlined /> {i18next.t("account:My Account")}</>,
|
||||
"/account"
|
||||
));
|
||||
if (Conf.EnableChatPages) {
|
||||
items.push(Setting.getItem(<><CommentOutlined /> {i18next.t("account:Chats & Messages")}</>,
|
||||
"/chat"
|
||||
));
|
||||
}
|
||||
}
|
||||
items.push(Setting.getItem(<><LogoutOutlined /> {i18next.t("account:Logout")}</>,
|
||||
"/logout"));
|
||||
@@ -378,8 +368,6 @@ class App extends Component {
|
||||
this.props.history.push("/account");
|
||||
} else if (e.key === "/subscription") {
|
||||
this.props.history.push("/subscription");
|
||||
} else if (e.key === "/chat") {
|
||||
this.props.history.push("/chat");
|
||||
} else if (e.key === "/logout") {
|
||||
this.logout();
|
||||
}
|
||||
@@ -481,6 +469,10 @@ class App extends Component {
|
||||
res.push(Setting.getItem(<Link to="/adapters">{i18next.t("general:Adapters")}</Link>,
|
||||
"/adapters"
|
||||
));
|
||||
|
||||
res.push(Setting.getItem(<Link to="/enforcers">{i18next.t("general:Enforcers")}</Link>,
|
||||
"/enforcers"
|
||||
));
|
||||
}
|
||||
|
||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||
@@ -492,16 +484,6 @@ class App extends Component {
|
||||
"/providers"
|
||||
));
|
||||
|
||||
if (Conf.EnableChatPages) {
|
||||
res.push(Setting.getItem(<Link to="/chats">{i18next.t("general:Chats")}</Link>,
|
||||
"/chats"
|
||||
));
|
||||
|
||||
res.push(Setting.getItem(<Link to="/messages">{i18next.t("general:Messages")}</Link>,
|
||||
"/messages"
|
||||
));
|
||||
}
|
||||
|
||||
res.push(Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>,
|
||||
"/resources"
|
||||
));
|
||||
@@ -599,6 +581,8 @@ class App extends Component {
|
||||
<Route exact path="/permissions/:organizationName/:permissionName" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/models" render={(props) => this.renderLoginIfNotLoggedIn(<ModelListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/models/:organizationName/:modelName" render={(props) => this.renderLoginIfNotLoggedIn(<ModelEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/enforcers" render={(props) => this.renderLoginIfNotLoggedIn(<EnforcerListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/enforcers/:organizationName/:enforcerName" render={(props) => this.renderLoginIfNotLoggedIn(<EnforcerEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/adapters" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/adapters/:organizationName/:adapterName" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/providers" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderListPage account={this.state.account} {...props} />)} />
|
||||
@@ -618,11 +602,6 @@ class App extends Component {
|
||||
<Route exact path="/syncers/:syncerName" render={(props) => this.renderLoginIfNotLoggedIn(<SyncerEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/certs" render={(props) => this.renderLoginIfNotLoggedIn(<CertListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/certs/:organizationName/:certName" render={(props) => this.renderLoginIfNotLoggedIn(<CertEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/chats" render={(props) => this.renderLoginIfNotLoggedIn(<ChatListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/chats/:chatName" render={(props) => this.renderLoginIfNotLoggedIn(<ChatEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/chat" render={(props) => this.renderLoginIfNotLoggedIn(<ChatPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/messages" render={(props) => this.renderLoginIfNotLoggedIn(<MessageListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/messages/:messageName" render={(props) => this.renderLoginIfNotLoggedIn(<MessageEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/plans" render={(props) => this.renderLoginIfNotLoggedIn(<PlanListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/plans/:organizationName/:planName" render={(props) => this.renderLoginIfNotLoggedIn(<PlanEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/pricings" render={(props) => this.renderLoginIfNotLoggedIn(<PricingListPage account={this.state.account} {...props} />)} />
|
||||
@@ -631,10 +610,10 @@ class App extends Component {
|
||||
<Route exact path="/subscriptions/:organizationName/:subscriptionName" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/products/:organizationName/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/products/:organizationName/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/payments/:organizationName/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/payments/:organizationName/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/mfa/setup" render={(props) => this.renderLoginIfNotLoggedIn(<MfaSetupPage account={this.state.account} onfinish={() => this.setState({requiredEnableMfa: false})} {...props} />)} />
|
||||
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
||||
@@ -658,8 +637,7 @@ class App extends Component {
|
||||
};
|
||||
|
||||
isWithoutCard() {
|
||||
return Setting.isMobile() || window.location.pathname === "/chat" ||
|
||||
window.location.pathname.startsWith("/trees");
|
||||
return Setting.isMobile() || window.location.pathname.startsWith("/trees");
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
|
@@ -1,217 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Alert, Avatar, Input, List, Spin} from "antd";
|
||||
import {CopyOutlined, DislikeOutlined, LikeOutlined, SendOutlined} from "@ant-design/icons";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {TextArea} = Input;
|
||||
|
||||
class ChatBox extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inputValue: "",
|
||||
};
|
||||
|
||||
this.listContainerRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.messages !== this.props.messages && this.props.messages !== undefined && this.props.messages !== null) {
|
||||
this.scrollToListItem(this.props.messages.length);
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown = (e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
|
||||
if (this.state.inputValue !== "") {
|
||||
this.send(this.state.inputValue);
|
||||
this.setState({inputValue: ""});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scrollToListItem(index) {
|
||||
const listContainerElement = this.listContainerRef.current;
|
||||
|
||||
if (!listContainerElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetItem = listContainerElement.querySelector(
|
||||
`#chatbox-list-item-${index}`
|
||||
);
|
||||
|
||||
if (!targetItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollDistance = targetItem.offsetTop - listContainerElement.offsetTop;
|
||||
|
||||
listContainerElement.scrollTo({
|
||||
top: scrollDistance,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
|
||||
send = (text) => {
|
||||
this.props.sendMessage(text);
|
||||
this.setState({inputValue: ""});
|
||||
};
|
||||
|
||||
renderText(text) {
|
||||
const lines = text.split("\n").map((line, index) => (
|
||||
<React.Fragment key={index}>
|
||||
{line}
|
||||
<br />
|
||||
</React.Fragment>
|
||||
));
|
||||
return <div>{lines}</div>;
|
||||
}
|
||||
|
||||
renderList() {
|
||||
if (this.props.messages === undefined || this.props.messages === null) {
|
||||
return (
|
||||
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "20%"}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={this.listContainerRef} style={{position: "relative", maxHeight: "calc(100vh - 140px)", overflowY: "auto"}}>
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={[...this.props.messages, {}]}
|
||||
renderItem={(item, index) => {
|
||||
if (Object.keys(item).length === 0 && item.constructor === Object) {
|
||||
return <List.Item id={`chatbox-list-item-${index}`} style={{
|
||||
height: "160px",
|
||||
backgroundColor: index % 2 === 0 ? "white" : "rgb(247,247,248)",
|
||||
borderBottom: "1px solid rgb(229, 229, 229)",
|
||||
position: "relative",
|
||||
}} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<List.Item id={`chatbox-list-item-${index}`} style={{
|
||||
backgroundColor: index % 2 === 0 ? "white" : "rgb(247,247,248)",
|
||||
borderBottom: "1px solid rgb(229, 229, 229)",
|
||||
position: "relative",
|
||||
}}>
|
||||
<div style={{width: "800px", margin: "0 auto", position: "relative"}}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar style={{width: "30px", height: "30px", borderRadius: "3px"}} src={item.author === `${this.props.account.owner}/${this.props.account.name}` ? this.props.account.avatar : "https://cdn.casbin.com/casdoor/resource/built-in/admin/gpt.png"} />}
|
||||
title={
|
||||
<div style={{fontSize: "16px", fontWeight: "normal", lineHeight: "24px", marginTop: "-15px", marginLeft: "5px", marginRight: "80px"}}>
|
||||
{
|
||||
!item.text.includes("#ERROR#") ? this.renderText(item.text) : (
|
||||
<Alert message={item.text.slice("#ERROR#: ".length)} type="error" showIcon />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<div style={{position: "absolute", top: "0px", right: "0px"}}
|
||||
>
|
||||
<CopyOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
|
||||
<LikeOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
|
||||
<DislikeOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
|
||||
</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div style={{
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: "120px",
|
||||
background: "linear-gradient(transparent 0%, rgba(255, 255, 255, 0.8) 50%, white 100%)",
|
||||
pointerEvents: "none",
|
||||
}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderInput() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
bottom: "90px",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{position: "relative", width: "760px", marginLeft: "-280px"}}>
|
||||
<TextArea
|
||||
placeholder={"Send a message..."}
|
||||
autoSize={{maxRows: 8}}
|
||||
value={this.state.inputValue}
|
||||
onChange={(e) => this.setState({inputValue: e.target.value})}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
style={{
|
||||
fontSize: "16px",
|
||||
fontWeight: "normal",
|
||||
lineHeight: "24px",
|
||||
width: "770px",
|
||||
height: "48px",
|
||||
borderRadius: "6px",
|
||||
borderColor: "rgb(229,229,229)",
|
||||
boxShadow: "0 0 15px rgba(0, 0, 0, 0.1)",
|
||||
paddingLeft: "17px",
|
||||
paddingRight: "17px",
|
||||
paddingTop: "12px",
|
||||
paddingBottom: "12px",
|
||||
}}
|
||||
suffix={<SendOutlined style={{color: "rgb(210,210,217"}} onClick={() => this.send(this.state.inputValue)} />}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<SendOutlined
|
||||
style={{
|
||||
color: this.state.inputValue === "" ? "rgb(210,210,217)" : "rgb(142,142,160)",
|
||||
position: "absolute",
|
||||
bottom: "17px",
|
||||
right: "17px",
|
||||
}}
|
||||
onClick={() => this.send(this.state.inputValue)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.renderList()
|
||||
}
|
||||
{
|
||||
this.renderInput()
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatBox;
|
@@ -1,257 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from "antd";
|
||||
import * as ChatBackend from "./backend/ChatBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
class ChatEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
chatName: props.match.params.chatName,
|
||||
chat: null,
|
||||
organizations: [],
|
||||
users: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getChat();
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getChat() {
|
||||
ChatBackend.getChat("admin", this.state.chatName)
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
chat: res.data,
|
||||
});
|
||||
|
||||
this.getUsers(res.data.organization);
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getUsers(organizationName) {
|
||||
UserBackend.getUsers(organizationName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseChatField(key, value) {
|
||||
if ([].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
updateChatField(key, value) {
|
||||
value = this.parseChatField(key, value);
|
||||
|
||||
const chat = this.state.chat;
|
||||
chat[key] = value;
|
||||
this.setState({
|
||||
chat: chat,
|
||||
});
|
||||
}
|
||||
|
||||
renderChat() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("chat:New Chat") : i18next.t("chat:Edit Chat")}
|
||||
<Button onClick={() => this.submitChatEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitChatEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteChat()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={!Setting.isAdminUser(this.props.account)} style={{width: "100%"}} value={this.state.chat.organization} onChange={(value => {this.updateChatField("organization", value);})}
|
||||
options={this.state.organizations.map((organization) => Setting.getOption(organization.name, organization.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.chat.name} onChange={e => {
|
||||
this.updateChatField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.chat.displayName} onChange={e => {
|
||||
this.updateChatField("displayName", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.chat.type} onChange={(value => {
|
||||
this.updateChatField("type", value);
|
||||
})}
|
||||
options={[
|
||||
{value: "Single", name: i18next.t("chat:Single")},
|
||||
{value: "Group", name: i18next.t("chat:Group")},
|
||||
{value: "AI", name: i18next.t("chat:AI")},
|
||||
].map((item) => Setting.getOption(item.name, item.value))}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Category"), i18next.t("provider:Category - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.chat.category} onChange={e => {
|
||||
this.updateChatField("category", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("chat:User1"), i18next.t("chat:User1 - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.chat.user1} onChange={(value => {this.updateChatField("user1", value);})}
|
||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("chat:User2"), i18next.t("chat:User2 - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.chat.user2} onChange={(value => {this.updateChatField("user2", value);})}
|
||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Users"), i18next.t("chat:Users - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.chat.users}
|
||||
onChange={(value => {this.updateChatField("users", value);})}
|
||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
submitChatEdit(willExist) {
|
||||
const chat = Setting.deepCopy(this.state.chat);
|
||||
ChatBackend.updateChat(this.state.chat.owner, this.state.chatName, chat)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||
this.setState({
|
||||
chatName: this.state.chat.name,
|
||||
});
|
||||
|
||||
if (willExist) {
|
||||
this.props.history.push("/chats");
|
||||
} else {
|
||||
this.props.history.push(`/chats/${this.state.chat.name}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
this.updateChatField("name", this.state.chatName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteChat() {
|
||||
ChatBackend.deleteChat(this.state.chat)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push("/chats");
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.chat !== null ? this.renderChat() : null
|
||||
}
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button size="large" onClick={() => this.submitChatEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitChatEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteChat()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatEditPage;
|
@@ -1,297 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ChatBackend from "./backend/ChatBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||
|
||||
class ChatListPage extends BaseListPage {
|
||||
newChat() {
|
||||
const randomName = Setting.getRandomName();
|
||||
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||
return {
|
||||
owner: "admin", // this.props.account.applicationName,
|
||||
name: `chat_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
updatedTime: moment().format(),
|
||||
organization: organizationName,
|
||||
displayName: `New Chat - ${randomName}`,
|
||||
type: "Single",
|
||||
category: "Chat Category - 1",
|
||||
user1: `${this.props.account.owner}/${this.props.account.name}`,
|
||||
user2: "",
|
||||
users: [`${this.props.account.owner}/${this.props.account.name}`],
|
||||
messageCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
addChat() {
|
||||
const newChat = this.newChat();
|
||||
ChatBackend.addChat(newChat)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push({pathname: `/chats/${newChat.name}`, mode: "add"});
|
||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteChat(i) {
|
||||
ChatBackend.deleteChat(this.state.data[i])
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||
this.setState({
|
||||
data: Setting.deleteRow(this.state.data, i),
|
||||
pagination: {total: this.state.pagination.total - 1},
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(chats) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "organization",
|
||||
key: "organization",
|
||||
width: "150px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("organization"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "120px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/chats/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "150px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Updated time"),
|
||||
dataIndex: "updatedTime",
|
||||
key: "updatedTime",
|
||||
width: "15 0px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("provider:Type"),
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: "110px",
|
||||
sorter: true,
|
||||
filterMultiple: false,
|
||||
filters: [
|
||||
{text: "Single", value: "Single"},
|
||||
{text: "Group", value: "Group"},
|
||||
{text: "AI", value: "AI"},
|
||||
],
|
||||
render: (text, record, index) => {
|
||||
return i18next.t(`chat:${text}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("provider:Category"),
|
||||
dataIndex: "category",
|
||||
key: "category",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("category"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("chat:User1"),
|
||||
dataIndex: "user1",
|
||||
key: "user1",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("user1"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("chat:User2"),
|
||||
dataIndex: "user2",
|
||||
key: "user2",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("user2"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Users"),
|
||||
dataIndex: "users",
|
||||
key: "users",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("users"),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getTags(text, "users");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("chat:Message count"),
|
||||
dataIndex: "messageCount",
|
||||
key: "messageCount",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("messageCount"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/chats/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteChat(index)}
|
||||
>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const paginationProps = {
|
||||
total: this.state.pagination.total,
|
||||
showQuickJumper: true,
|
||||
showSizeChanger: true,
|
||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={chats} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||
title={() => (
|
||||
<div>
|
||||
{i18next.t("general:Chats")}
|
||||
<Button type="primary" size="small" onClick={this.addChat.bind(this)}>{i18next.t("general:Add")}</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={this.state.loading}
|
||||
onChange={this.handleTableChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
fetch = (params = {}) => {
|
||||
let field = params.searchedColumn, value = params.searchText;
|
||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||
if (params.category !== undefined && params.category !== null) {
|
||||
field = "category";
|
||||
value = params.category;
|
||||
} else if (params.type !== undefined && params.type !== null) {
|
||||
field = "type";
|
||||
value = params.type;
|
||||
}
|
||||
this.setState({loading: true});
|
||||
ChatBackend.getChats("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
data: res.data,
|
||||
pagination: {
|
||||
...params.pagination,
|
||||
total: res.data2,
|
||||
},
|
||||
searchText: params.searchText,
|
||||
searchedColumn: params.searchedColumn,
|
||||
});
|
||||
} else {
|
||||
if (Setting.isResponseDenied(res)) {
|
||||
this.setState({
|
||||
isAuthorized: false,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default ChatListPage;
|
@@ -1,178 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Menu} from "antd";
|
||||
import {DeleteOutlined, LayoutOutlined, PlusOutlined} from "@ant-design/icons";
|
||||
|
||||
class ChatMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const items = this.chatsToItems(this.props.chats);
|
||||
const openKeys = items.map((item) => item.key);
|
||||
|
||||
this.state = {
|
||||
openKeys: openKeys,
|
||||
selectedKeys: ["0-0"],
|
||||
};
|
||||
}
|
||||
|
||||
chatsToItems(chats) {
|
||||
const categories = {};
|
||||
chats.forEach((chat) => {
|
||||
if (!categories[chat.category]) {
|
||||
categories[chat.category] = [];
|
||||
}
|
||||
categories[chat.category].push(chat);
|
||||
});
|
||||
|
||||
const selectedKeys = this.state === undefined ? [] : this.state.selectedKeys;
|
||||
return Object.keys(categories).map((category, index) => {
|
||||
return {
|
||||
key: `${index}`,
|
||||
icon: <LayoutOutlined />,
|
||||
label: category,
|
||||
children: categories[category].map((chat, chatIndex) => {
|
||||
const globalChatIndex = chats.indexOf(chat);
|
||||
const isSelected = selectedKeys.includes(`${index}-${chatIndex}`);
|
||||
return {
|
||||
key: `${index}-${chatIndex}`,
|
||||
index: globalChatIndex,
|
||||
label: (
|
||||
<div
|
||||
className="menu-item-container"
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
{chat.displayName}
|
||||
{isSelected && (
|
||||
<DeleteOutlined
|
||||
className="menu-item-delete-icon"
|
||||
style={{
|
||||
visibility: "visible",
|
||||
color: "inherit",
|
||||
transition: "color 0.3s",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.color = "rgba(89,54,213,0.6)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.color = "inherit";
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
e.currentTarget.style.color = "rgba(89,54,213,0.4)";
|
||||
}}
|
||||
onMouseUp={(e) => {
|
||||
e.currentTarget.style.color = "rgba(89,54,213,0.6)";
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (this.props.onDeleteChat) {
|
||||
this.props.onDeleteChat(globalChatIndex);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onSelect = (info) => {
|
||||
const [categoryIndex, chatIndex] = info.selectedKeys[0].split("-").map(Number);
|
||||
const selectedItem = this.chatsToItems(this.props.chats)[categoryIndex].children[chatIndex];
|
||||
this.setState({selectedKeys: [`${categoryIndex}-${chatIndex}`]});
|
||||
|
||||
if (this.props.onSelectChat) {
|
||||
this.props.onSelectChat(selectedItem.index);
|
||||
}
|
||||
};
|
||||
|
||||
getRootSubmenuKeys(items) {
|
||||
return items.map((item, index) => `${index}`);
|
||||
}
|
||||
|
||||
setSelectedKeyToNewChat(chats) {
|
||||
const items = this.chatsToItems(chats);
|
||||
const openKeys = items.map((item) => item.key);
|
||||
|
||||
this.setState({
|
||||
openKeys: openKeys,
|
||||
selectedKeys: ["0-0"],
|
||||
});
|
||||
}
|
||||
|
||||
onOpenChange = (keys) => {
|
||||
const items = this.chatsToItems(this.props.chats);
|
||||
const rootSubmenuKeys = this.getRootSubmenuKeys(items);
|
||||
const latestOpenKey = keys.find((key) => this.state.openKeys.indexOf(key) === -1);
|
||||
|
||||
if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
||||
this.setState({openKeys: keys});
|
||||
} else {
|
||||
this.setState({openKeys: latestOpenKey ? [latestOpenKey] : []});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const items = this.chatsToItems(this.props.chats);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
icon={<PlusOutlined />}
|
||||
style={{
|
||||
width: "calc(100% - 8px)",
|
||||
height: "40px",
|
||||
margin: "4px",
|
||||
borderColor: "rgb(229,229,229)",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.borderColor = "rgba(89,54,213,0.6)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.borderColor = "rgba(0, 0, 0, 0.1)";
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
e.currentTarget.style.borderColor = "rgba(89,54,213,0.4)";
|
||||
}}
|
||||
onMouseUp={(e) => {
|
||||
e.currentTarget.style.borderColor = "rgba(89,54,213,0.6)";
|
||||
}}
|
||||
onClick={this.props.onAddChat}
|
||||
>
|
||||
New Chat
|
||||
</Button>
|
||||
<Menu
|
||||
style={{maxHeight: "calc(100vh - 140px - 40px - 8px)", overflowY: "auto"}}
|
||||
mode="inline"
|
||||
openKeys={this.state.openKeys}
|
||||
selectedKeys={this.state.selectedKeys}
|
||||
onOpenChange={this.onOpenChange}
|
||||
onSelect={this.onSelect}
|
||||
items={items}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatMenu;
|
@@ -1,292 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Spin} from "antd";
|
||||
import moment from "moment";
|
||||
import ChatMenu from "./ChatMenu";
|
||||
import ChatBox from "./ChatBox";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ChatBackend from "./backend/ChatBackend";
|
||||
import * as MessageBackend from "./backend/MessageBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
|
||||
class ChatPage extends BaseListPage {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.menu = React.createRef();
|
||||
}
|
||||
|
||||
newChat(chat) {
|
||||
const randomName = Setting.getRandomName();
|
||||
return {
|
||||
owner: "admin", // this.props.account.applicationName,
|
||||
name: `chat_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
updatedTime: moment().format(),
|
||||
organization: this.props.account.owner,
|
||||
displayName: `New Chat - ${randomName}`,
|
||||
type: "AI",
|
||||
category: chat !== undefined ? chat.category : "Chat Category - 1",
|
||||
user1: `${this.props.account.owner}/${this.props.account.name}`,
|
||||
user2: "",
|
||||
users: [`${this.props.account.owner}/${this.props.account.name}`],
|
||||
messageCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
newMessage(text) {
|
||||
const randomName = Setting.getRandomName();
|
||||
return {
|
||||
owner: this.props.account.owner, // this.props.account.messagename,
|
||||
name: `message_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
organization: this.props.account.owner,
|
||||
chat: this.state.chatName,
|
||||
replyTo: "",
|
||||
author: `${this.props.account.owner}/${this.props.account.name}`,
|
||||
text: text,
|
||||
};
|
||||
}
|
||||
|
||||
sendMessage(text) {
|
||||
const newMessage = this.newMessage(text);
|
||||
MessageBackend.addMessage(newMessage)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.getMessages(this.state.chatName);
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
getMessages(chatName) {
|
||||
MessageBackend.getChatMessages(chatName)
|
||||
.then((res) => {
|
||||
const messages = res.data;
|
||||
this.setState({
|
||||
messages: messages,
|
||||
});
|
||||
|
||||
if (messages.length > 0) {
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
if (lastMessage.author === "AI" && lastMessage.replyTo !== "" && lastMessage.text === "") {
|
||||
let text = "";
|
||||
MessageBackend.getMessageAnswer(lastMessage.owner, lastMessage.name, (data) => {
|
||||
if (data === "") {
|
||||
data = "\n";
|
||||
}
|
||||
|
||||
const lastMessage2 = Setting.deepCopy(lastMessage);
|
||||
text += data;
|
||||
lastMessage2.text = text;
|
||||
messages[messages.length - 1] = lastMessage2;
|
||||
this.setState({
|
||||
messages: messages,
|
||||
});
|
||||
}, (error) => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to get answer")}: ${error}`);
|
||||
|
||||
const lastMessage2 = Setting.deepCopy(lastMessage);
|
||||
lastMessage2.text = `#ERROR#: ${error}`;
|
||||
messages[messages.length - 1] = lastMessage2;
|
||||
this.setState({
|
||||
messages: messages,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Setting.scrollToDiv(`chatbox-list-item-${messages.length}`);
|
||||
});
|
||||
}
|
||||
|
||||
addChat(chat) {
|
||||
const newChat = this.newChat(chat);
|
||||
ChatBackend.addChat(newChat)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||
this.setState({
|
||||
chatName: newChat.name,
|
||||
messages: null,
|
||||
});
|
||||
this.getMessages(newChat.name);
|
||||
|
||||
const {pagination} = this.state;
|
||||
this.fetch({pagination}, false);
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteChat(chats, i, chat) {
|
||||
ChatBackend.deleteChat(chat)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||
const data = Setting.deleteRow(this.state.data, i);
|
||||
const j = Math.min(i, data.length - 1);
|
||||
if (j < 0) {
|
||||
this.setState({
|
||||
chatName: undefined,
|
||||
messages: [],
|
||||
data: data,
|
||||
});
|
||||
} else {
|
||||
const focusedChat = data[j];
|
||||
this.setState({
|
||||
chatName: focusedChat.name,
|
||||
messages: null,
|
||||
data: data,
|
||||
});
|
||||
this.getMessages(focusedChat.name);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
getCurrentChat() {
|
||||
return this.state.data.filter(chat => chat.name === this.state.chatName)[0];
|
||||
}
|
||||
|
||||
renderTable(chats) {
|
||||
const onSelectChat = (i) => {
|
||||
const chat = chats[i];
|
||||
this.setState({
|
||||
chatName: chat.name,
|
||||
messages: null,
|
||||
});
|
||||
this.getMessages(chat.name);
|
||||
};
|
||||
|
||||
const onAddChat = () => {
|
||||
const chat = this.getCurrentChat();
|
||||
this.addChat(chat);
|
||||
};
|
||||
|
||||
const onDeleteChat = (i) => {
|
||||
const chat = chats[i];
|
||||
this.deleteChat(chats, i, chat);
|
||||
};
|
||||
|
||||
if (this.state.loading) {
|
||||
return (
|
||||
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "10%"}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{display: "flex", height: "calc(100vh - 140px)"}}>
|
||||
<div style={{width: "250px", height: "100%", backgroundColor: "white", borderRight: "1px solid rgb(245,245,245)", borderBottom: "1px solid rgb(245,245,245)"}}>
|
||||
<ChatMenu ref={this.menu} chats={chats} onSelectChat={onSelectChat} onAddChat={onAddChat} onDeleteChat={onDeleteChat} />
|
||||
</div>
|
||||
<div style={{flex: 1, height: "100%", backgroundColor: "white", position: "relative"}}>
|
||||
{
|
||||
(this.state.messages === undefined || this.state.messages === null) ? null : (
|
||||
<div style={{
|
||||
position: "absolute",
|
||||
top: -50,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage: "url(https://cdn.casbin.org/img/casdoor-logo_1185x256.png)",
|
||||
backgroundPosition: "center",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: "200px auto",
|
||||
backgroundBlendMode: "luminosity",
|
||||
filter: "grayscale(80%) brightness(140%) contrast(90%)",
|
||||
opacity: 0.5,
|
||||
pointerEvents: "none",
|
||||
}}>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<ChatBox messages={this.state.messages || []} sendMessage={(text) => {this.sendMessage(text);}} account={this.props.account} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
fetch = (params = {}, setLoading = true) => {
|
||||
let field = params.searchedColumn, value = params.searchText;
|
||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||
if (params.category !== undefined && params.category !== null) {
|
||||
field = "category";
|
||||
value = params.category;
|
||||
} else if (params.type !== undefined && params.type !== null) {
|
||||
field = "type";
|
||||
value = params.type;
|
||||
}
|
||||
if (setLoading) {
|
||||
this.setState({loading: true});
|
||||
}
|
||||
ChatBackend.getChats("admin", params.pagination.current, -1, field, value, sortField, sortOrder)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
messages: [],
|
||||
pagination: {
|
||||
...params.pagination,
|
||||
total: res.data2,
|
||||
},
|
||||
searchText: params.searchText,
|
||||
searchedColumn: params.searchedColumn,
|
||||
});
|
||||
|
||||
const chats = res.data;
|
||||
if (this.state.chatName === undefined && chats.length > 0) {
|
||||
const chat = chats[0];
|
||||
this.getMessages(chat.name);
|
||||
this.setState({
|
||||
chatName: chat.name,
|
||||
});
|
||||
}
|
||||
|
||||
if (!setLoading) {
|
||||
this.menu.current.setSelectedKeyToNewChat(chats);
|
||||
}
|
||||
} else {
|
||||
if (Setting.isResponseDenied(res)) {
|
||||
this.setState({
|
||||
isAuthorized: false,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default ChatPage;
|
@@ -21,7 +21,6 @@ export const ForceLanguage = "";
|
||||
export const DefaultLanguage = "en";
|
||||
|
||||
export const EnableExtraPages = true;
|
||||
export const EnableChatPages = true;
|
||||
|
||||
export const InitThemeAlgorithm = true;
|
||||
export const ThemeDefault = {
|
||||
|
257
web/src/EnforcerEditPage.js
Normal file
257
web/src/EnforcerEditPage.js
Normal file
@@ -0,0 +1,257 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
class EnforcerEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||
enforcerName: props.match.params.enforcerName,
|
||||
enforcer: null,
|
||||
organizations: [],
|
||||
models: [],
|
||||
adapters: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getEnforcer();
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getEnforcer() {
|
||||
EnforcerBackend.getEnforcer(this.state.organizationName, this.state.enforcerName)
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
enforcer: res.data,
|
||||
});
|
||||
|
||||
this.getModels(this.state.organizationName);
|
||||
this.getAdapters(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getModels(organizationName) {
|
||||
ModelBackend.getModels(organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
models: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getAdapters(organizationName) {
|
||||
AdapterBackend.getAdapters(organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
adapters: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseEnforcerField(key, value) {
|
||||
if ([""].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
updateEnforcerField(key, value) {
|
||||
value = this.parseEnforcerField(key, value);
|
||||
|
||||
const enforcer = this.state.enforcer;
|
||||
enforcer[key] = value;
|
||||
this.setState({
|
||||
enforcer: enforcer,
|
||||
});
|
||||
}
|
||||
|
||||
renderEnforcer() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("enforcer:New Enforcer") : i18next.t("enforcer:Edit Enforcer")}
|
||||
<Button onClick={() => this.submitEnforcerEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitEnforcerEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteEnforcer()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account) || Setting.builtInObject(this.state.enforcer)} value={this.state.enforcer.owner} onChange={(owner => {
|
||||
this.updateEnforcerField("owner", owner);
|
||||
this.getModels(owner);
|
||||
this.getAdapters(owner);
|
||||
})}
|
||||
options={this.state.organizations.map((organization) => Setting.getOption(organization.name, organization.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input disabled={Setting.builtInObject(this.state.enforcer)} value={this.state.enforcer.name} onChange={e => {
|
||||
this.updateEnforcerField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.enforcer.displayName} onChange={e => {
|
||||
this.updateEnforcerField("displayName", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Description"), i18next.t("general:Description - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.enforcer.description} onChange={e => {
|
||||
this.updateEnforcerField("description", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Model"), i18next.t("general:Model - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.model} onChange={(model => {
|
||||
this.updateEnforcerField("model", model);
|
||||
})}
|
||||
options={this.state.models.map((model) => Setting.getOption(model.displayName, `${model.owner}/${model.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Adapter"), i18next.t("general:Adapter - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.adapter} onChange={(adapter => {
|
||||
this.updateEnforcerField("adapter", adapter);
|
||||
})}
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(adapter.name, `${adapter.owner}/${adapter.name}`))
|
||||
} />
|
||||
</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"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.enforcer.isEnabled} onChange={checked => {
|
||||
this.updateEnforcerField("isEnabled", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
submitEnforcerEdit(willExist) {
|
||||
const enforcer = Setting.deepCopy(this.state.enforcer);
|
||||
EnforcerBackend.updateEnforcer(this.state.organizationName, this.state.enforcerName, enforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||
this.setState({
|
||||
enforcerName: this.state.enforcer.name,
|
||||
});
|
||||
|
||||
if (willExist) {
|
||||
this.props.history.push("/enforcers");
|
||||
} else {
|
||||
this.props.history.push(`/enforcers/${this.state.enforcer.owner}/${this.state.enforcer.name}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
this.updateEnforcerField("name", this.state.enforcerName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteEnforcer() {
|
||||
EnforcerBackend.deleteEnforcer(this.state.enforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push("/enforcers");
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.enforcer !== null ? this.renderEnforcer() : null
|
||||
}
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button size="large" onClick={() => this.submitEnforcerEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitEnforcerEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteEnforcer()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EnforcerEditPage;
|
@@ -14,36 +14,33 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as MessageBackend from "./backend/MessageBackend";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||
|
||||
class MessageListPage extends BaseListPage {
|
||||
newMessage() {
|
||||
class EnforcerListPage extends BaseListPage {
|
||||
newEnforcer() {
|
||||
const randomName = Setting.getRandomName();
|
||||
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||
const owner = Setting.getRequestOrganization(this.props.account);
|
||||
return {
|
||||
owner: "admin", // this.props.account.messagename,
|
||||
name: `message_${randomName}`,
|
||||
owner: owner,
|
||||
name: `enforcer_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
organization: organizationName,
|
||||
chat: "",
|
||||
replyTo: "",
|
||||
author: `${this.props.account.owner}/${this.props.account.name}`,
|
||||
text: "",
|
||||
displayName: `New Enforcer - ${randomName}`,
|
||||
isEnabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
addMessage() {
|
||||
const newMessage = this.newMessage();
|
||||
MessageBackend.addMessage(newMessage)
|
||||
addEnforcer() {
|
||||
const newEnforcer = this.newEnforcer();
|
||||
EnforcerBackend.addEnforcer(newEnforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push({pathname: `/messages/${newMessage.name}`, mode: "add"});
|
||||
this.props.history.push({pathname: `/enforcers/${newEnforcer.owner}/${newEnforcer.name}`, mode: "add"});
|
||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
@@ -54,8 +51,8 @@ class MessageListPage extends BaseListPage {
|
||||
});
|
||||
}
|
||||
|
||||
deleteMessage(i) {
|
||||
MessageBackend.deleteMessage(this.state.data[i])
|
||||
deleteEnforcer(i) {
|
||||
EnforcerBackend.deleteEnforcer(this.state.data[i])
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||
@@ -72,16 +69,31 @@ class MessageListPage extends BaseListPage {
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(messages) {
|
||||
renderTable(enforcers) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "organization",
|
||||
key: "organization",
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "150px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("organization"),
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/enforcers/${record.owner}/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("owner"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
@@ -90,70 +102,36 @@ class MessageListPage extends BaseListPage {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "120px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/messages/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "150px",
|
||||
width: "160px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("message:Chat"),
|
||||
dataIndex: "chat",
|
||||
key: "chat",
|
||||
width: "120px",
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("chat"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/chats/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("message:Author"),
|
||||
dataIndex: "author",
|
||||
key: "author",
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
key: "isEnabled",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("author"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("message:Text"),
|
||||
dataIndex: "text",
|
||||
key: "text",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("text"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
@@ -163,10 +141,12 @@ class MessageListPage extends BaseListPage {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/messages/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary"
|
||||
onClick={() => this.props.history.push(`/enforcers/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
disabled={Setting.builtInObject(record)}
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteMessage(index)}
|
||||
onConfirm={() => this.deleteEnforcer(index)}
|
||||
>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
@@ -184,11 +164,13 @@ class MessageListPage extends BaseListPage {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={messages} rowKey={(record) => `${record.owner}/${record.name}`}size="middle" bordered pagination={paginationProps}
|
||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={enforcers} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered
|
||||
pagination={paginationProps}
|
||||
title={() => (
|
||||
<div>
|
||||
{i18next.t("general:Messages")}
|
||||
<Button type="primary" size="small" onClick={this.addMessage.bind(this)}>{i18next.t("general:Add")}</Button>
|
||||
{i18next.t("general:Enforcers")}
|
||||
<Button type="primary" size="small"
|
||||
onClick={this.addEnforcer.bind(this)}>{i18next.t("general:Add")}</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={this.state.loading}
|
||||
@@ -201,15 +183,12 @@ class MessageListPage extends BaseListPage {
|
||||
fetch = (params = {}) => {
|
||||
let field = params.searchedColumn, value = params.searchText;
|
||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||
if (params.category !== undefined && params.category !== null) {
|
||||
field = "category";
|
||||
value = params.category;
|
||||
} else if (params.type !== undefined && params.type !== null) {
|
||||
if (params.type !== undefined && params.type !== null) {
|
||||
field = "type";
|
||||
value = params.type;
|
||||
}
|
||||
this.setState({loading: true});
|
||||
MessageBackend.getMessages("admin", Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
EnforcerBackend.getEnforcers(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
@@ -237,4 +216,4 @@ class MessageListPage extends BaseListPage {
|
||||
};
|
||||
}
|
||||
|
||||
export default MessageListPage;
|
||||
export default EnforcerListPage;
|
@@ -1,233 +0,0 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from "antd";
|
||||
import * as ChatBackend from "./backend/ChatBackend";
|
||||
import * as MessageBackend from "./backend/MessageBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {TextArea} = Input;
|
||||
|
||||
class MessageEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
messageName: props.match.params.messageName,
|
||||
message: null,
|
||||
organizations: [],
|
||||
chats: [],
|
||||
users: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getMessage();
|
||||
this.getOrganizations();
|
||||
this.getChats();
|
||||
}
|
||||
|
||||
getMessage() {
|
||||
MessageBackend.getMessage("admin", this.state.messageName)
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
message: res.data,
|
||||
});
|
||||
this.getUsers(res.data.organization);
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getChats() {
|
||||
ChatBackend.getChats("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
chats: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getUsers(organizationName) {
|
||||
UserBackend.getUsers(organizationName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseMessageField(key, value) {
|
||||
if ([].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
updateMessageField(key, value) {
|
||||
value = this.parseMessageField(key, value);
|
||||
|
||||
const message = this.state.message;
|
||||
message[key] = value;
|
||||
this.setState({
|
||||
message: message,
|
||||
});
|
||||
}
|
||||
|
||||
renderMessage() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("message:New Message") : i18next.t("message:Edit Message")}
|
||||
<Button onClick={() => this.submitMessageEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitMessageEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteMessage()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={!Setting.isAdminUser(this.props.account)} style={{width: "100%"}} value={this.state.message.organization} onChange={(value => {this.updateMessageField("organization", value);})}
|
||||
options={this.state.organizations.map((organization) => Setting.getOption(organization.name, organization.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.message.name} onChange={e => {
|
||||
this.updateMessageField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("message:Chat"), i18next.t("message:Chat - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.message.chat} onChange={(value => {this.updateMessageField("chat", value);})}
|
||||
options={this.state.chats.map((chat) => Setting.getOption(chat.name, chat.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("message:Author"), i18next.t("message:Author - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.message.author} onChange={(value => {this.updateMessageField("author", value);})}
|
||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("message:Text"), i18next.t("message:Text - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<TextArea rows={10} value={this.state.message.text} onChange={e => {
|
||||
this.updateMessageField("text", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
submitMessageEdit(willExist) {
|
||||
const message = Setting.deepCopy(this.state.message);
|
||||
MessageBackend.updateMessage(this.state.message.owner, this.state.messageName, message)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||
this.setState({
|
||||
messageName: this.state.message.name,
|
||||
});
|
||||
|
||||
if (willExist) {
|
||||
this.props.history.push("/messages");
|
||||
} else {
|
||||
this.props.history.push(`/messages/${this.state.message.name}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
this.updateMessageField("name", this.state.messageName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteMessage() {
|
||||
MessageBackend.deleteMessage(this.state.message)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push("/messages");
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.message !== null ? this.renderMessage() : null
|
||||
}
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button size="large" onClick={() => this.submitMessageEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitMessageEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteMessage()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MessageEditPage;
|
@@ -105,7 +105,7 @@ class ModelEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.model.owner} onChange={(value => {this.updateModelField("owner", value);})}>
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account) || Setting.builtInObject(this.state.model)} value={this.state.model.owner} onChange={(value => {this.updateModelField("owner", value);})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class ModelEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.model.name} onChange={e => {
|
||||
<Input disabled={Setting.builtInObject(this.state.model)} value={this.state.model.name} onChange={e => {
|
||||
this.updateModelField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
@@ -152,6 +152,9 @@ class ModelEditPage extends React.Component {
|
||||
value={this.state.model.modelText}
|
||||
options={{mode: "properties", theme: "default"}}
|
||||
onBeforeChange={(editor, data, value) => {
|
||||
if (Setting.builtInObject(this.state.model)) {
|
||||
return;
|
||||
}
|
||||
this.updateModelField("modelText", value);
|
||||
}}
|
||||
/>
|
||||
|
@@ -160,6 +160,7 @@ class ModelListPage extends BaseListPage {
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary"
|
||||
onClick={() => this.props.history.push(`/models/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
disabled={Setting.builtInObject(record)}
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteModel(index)}
|
||||
>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user