casdoor/object/record.go

311 lines
7.1 KiB
Go
Raw Normal View History

2022-02-13 23:39:27 +08:00
// 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 (
"encoding/json"
2021-11-27 21:12:13 +08:00
"fmt"
"regexp"
2021-11-07 16:51:16 +08:00
"strings"
2022-09-29 19:44:08 +08:00
"github.com/beego/beego/context"
"github.com/casdoor/casdoor/conf"
2022-01-20 14:11:46 +08:00
"github.com/casdoor/casdoor/util"
2023-08-19 23:15:02 +08:00
"github.com/casvisor/casvisor-go-sdk/casvisorsdk"
)
var (
logPostOnly bool
passwordRegex *regexp.Regexp
)
2021-11-09 23:32:53 +08:00
func init() {
logPostOnly = conf.GetConfigBool("logPostOnly")
passwordRegex = regexp.MustCompile("\"password\":\"([^\"]*?)\"")
2021-11-09 23:32:53 +08:00
}
2021-11-07 16:51:16 +08:00
type Record struct {
2023-08-19 23:15:02 +08:00
casvisorsdk.Record
}
type Response struct {
Status string `json:"status"`
Msg string `json:"msg"`
}
func maskPassword(recordString string) string {
return passwordRegex.ReplaceAllString(recordString, "\"password\":\"***\"")
}
func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
clientIp := strings.Replace(util.GetClientIpFromRequest(ctx.Request), ": ", "", -1)
2021-11-07 16:51:16 +08:00
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
requestUri := util.FilterQuery(ctx.Request.RequestURI, []string{"accessToken"})
if len(requestUri) > 1000 {
requestUri = requestUri[0:1000]
}
2021-11-07 16:51:16 +08:00
2023-05-17 23:57:14 +08:00
object := ""
if ctx.Input.RequestBody != nil && len(ctx.Input.RequestBody) != 0 {
object = string(ctx.Input.RequestBody)
object = maskPassword(object)
2023-05-17 23:57:14 +08:00
}
respBytes, err := json.Marshal(ctx.Input.Data()["json"])
if err != nil {
return nil, err
}
var resp Response
err = json.Unmarshal(respBytes, &resp)
if err != nil {
return nil, err
}
2024-03-08 23:03:30 +08:00
language := ctx.Request.Header.Get("Accept-Language")
if len(language) > 2 {
language = language[0:2]
}
languageCode := conf.GetLanguage(language)
2023-08-19 23:15:02 +08:00
record := casvisorsdk.Record{
2021-11-07 17:36:52 +08:00
Name: util.GenerateId(),
CreatedTime: util.GetCurrentTime(),
ClientIp: clientIp,
2021-11-07 17:36:52 +08:00
User: "",
2021-11-09 23:24:13 +08:00
Method: ctx.Request.Method,
RequestUri: requestUri,
2021-11-07 17:36:52 +08:00
Action: action,
2024-03-08 23:03:30 +08:00
Language: languageCode,
2023-05-17 23:57:14 +08:00
Object: object,
StatusCode: 200,
Response: fmt.Sprintf("{status:\"%s\", msg:\"%s\"}", resp.Status, resp.Msg),
2021-11-07 23:53:17 +08:00
IsTriggered: false,
2021-11-07 16:51:16 +08:00
}
return &record, nil
2021-11-07 16:51:16 +08:00
}
func addRecord(record *casvisorsdk.Record) (int64, error) {
affected, err := ormer.Engine.Insert(record)
return affected, err
}
2023-08-19 23:15:02 +08:00
func AddRecord(record *casvisorsdk.Record) bool {
2021-11-09 23:32:53 +08:00
if logPostOnly {
if record.Method == "GET" {
return false
}
}
2021-11-20 16:21:15 +08:00
if record.Organization == "app" {
return false
}
2021-11-07 17:36:52 +08:00
record.Owner = record.Organization
record.Object = maskPassword(record.Object)
2021-11-07 23:53:17 +08:00
errWebhook := SendWebhooks(record)
if errWebhook == nil {
record.IsTriggered = true
2021-11-27 21:12:13 +08:00
} else {
fmt.Println(errWebhook)
2021-11-07 23:53:17 +08:00
}
2023-08-19 23:15:02 +08:00
if casvisorsdk.GetClient() == nil {
affected, err := addRecord(record)
if err != nil {
panic(err)
}
return affected != 0
}
2023-08-19 23:15:02 +08:00
affected, err := casvisorsdk.AddRecord(record)
if err != nil {
2023-10-05 00:11:13 +08:00
fmt.Printf("AddRecord() error: %s", err.Error())
}
2023-08-19 23:15:02 +08:00
return affected
}
2021-11-07 23:53:17 +08:00
func GetRecordCount(field, value string, filterRecord *casvisorsdk.Record) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
return session.Count(filterRecord)
}
func GetRecords() ([]*casvisorsdk.Record, error) {
records := []*casvisorsdk.Record{}
err := ormer.Engine.Desc("id").Find(&records)
if err != nil {
return records, err
}
return records, nil
}
func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder string, filterRecord *casvisorsdk.Record) ([]*casvisorsdk.Record, error) {
records := []*casvisorsdk.Record{}
if sortField == "" || sortOrder == "" {
sortField = "id"
sortOrder = "descend"
}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&records, filterRecord)
if err != nil {
return records, err
}
return records, nil
}
func GetRecordsByField(record *casvisorsdk.Record) ([]*casvisorsdk.Record, error) {
records := []*casvisorsdk.Record{}
err := ormer.Engine.Find(&records, record)
if err != nil {
return records, err
}
return records, nil
}
2024-03-27 15:15:40 +08:00
func CopyRecord(record *casvisorsdk.Record) *casvisorsdk.Record {
res := &casvisorsdk.Record{
Owner: record.Owner,
Name: record.Name,
CreatedTime: record.CreatedTime,
Organization: record.Organization,
ClientIp: record.ClientIp,
User: record.User,
Method: record.Method,
RequestUri: record.RequestUri,
Action: record.Action,
Language: record.Language,
Object: record.Object,
Response: record.Response,
IsTriggered: record.IsTriggered,
}
return res
}
2024-03-04 21:14:52 +08:00
func getFilteredWebhooks(webhooks []*Webhook, organization string, action string) []*Webhook {
res := []*Webhook{}
2021-11-07 23:53:17 +08:00
for _, webhook := range webhooks {
2021-12-26 21:02:56 +08:00
if !webhook.IsEnabled {
continue
}
2024-03-04 21:14:52 +08:00
if webhook.SingleOrgOnly {
if webhook.Organization != organization {
continue
}
}
2021-11-07 23:53:17 +08:00
matched := false
for _, event := range webhook.Events {
if action == event {
2021-11-07 23:53:17 +08:00
matched = true
break
}
}
if matched {
res = append(res, webhook)
}
}
return res
}
func addWebhookRecord(webhook *Webhook, record *casvisorsdk.Record, statusCode int, respBody string, sendError error) error {
if statusCode == 200 {
return nil
}
if len(respBody) > 300 {
respBody = respBody[0:300]
}
webhookRecord := &casvisorsdk.Record{
Owner: record.Owner,
Name: util.GenerateId(),
CreatedTime: util.GetCurrentTime(),
Organization: record.Organization,
User: record.User,
Method: webhook.Method,
Action: "send-webhook",
RequestUri: webhook.Url,
StatusCode: statusCode,
Response: respBody,
Language: record.Language,
IsTriggered: false,
}
if sendError != nil {
webhookRecord.Response = sendError.Error()
}
_, err := addRecord(webhookRecord)
return err
}
func SendWebhooks(record *casvisorsdk.Record) error {
2024-02-06 20:33:11 +08:00
webhooks, err := getWebhooksByOrganization("")
if err != nil {
return err
}
errs := []error{}
2024-03-04 21:14:52 +08:00
webhooks = getFilteredWebhooks(webhooks, record.Organization, record.Action)
for _, webhook := range webhooks {
var user *User
if webhook.IsUserExtended {
user, err = getUser(record.Organization, record.User)
if err != nil {
errs = append(errs, err)
continue
2022-01-01 11:15:04 +08:00
}
user, err = GetMaskedUser(user, false, err)
2021-11-07 23:53:17 +08:00
if err != nil {
errs = append(errs, err)
continue
2021-11-07 23:53:17 +08:00
}
}
statusCode, respBody, err := sendWebhook(webhook, record, user)
if err != nil {
errs = append(errs, err)
}
err = addWebhookRecord(webhook, record, statusCode, respBody, err)
if err != nil {
errs = append(errs, err)
}
2021-11-07 23:53:17 +08:00
}
if len(errs) > 0 {
errStrings := []string{}
for _, err := range errs {
errStrings = append(errStrings, err.Error())
}
return fmt.Errorf(strings.Join(errStrings, " | "))
}
2021-11-07 23:53:17 +08:00
return nil
}