feat: support checking whether send-webhook API has error (#2944)

* feat: add webhook response for record

* refactor: refactor SendWebhook and use readall to read response body

* fix: improve code format

* fix: improve code format

* fix: improve code format
This commit is contained in:
DacongDA 2024-05-12 20:30:15 +08:00 committed by GitHub
parent 0ecc1d599f
commit b6b0b7d318
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 149 additions and 35 deletions

2
go.mod
View File

@ -14,7 +14,7 @@ require (
github.com/casdoor/notify v0.45.0
github.com/casdoor/oss v1.6.0
github.com/casdoor/xorm-adapter/v3 v3.1.0
github.com/casvisor/casvisor-go-sdk v1.3.0
github.com/casvisor/casvisor-go-sdk v1.4.0
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
github.com/denisenkom/go-mssqldb v0.9.0
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect

4
go.sum
View File

@ -1095,8 +1095,8 @@ github.com/casdoor/oss v1.6.0 h1:IOWrGLJ+VO82qS796eaRnzFPPA1Sn3cotYTi7O/VIlQ=
github.com/casdoor/oss v1.6.0/go.mod h1:rJAWA0hLhtu94t6IRpotLUkXO1NWMASirywQYaGizJE=
github.com/casdoor/xorm-adapter/v3 v3.1.0 h1:NodWayRtSLVSeCvL9H3Hc61k0G17KhV9IymTCNfh3kk=
github.com/casdoor/xorm-adapter/v3 v3.1.0/go.mod h1:4WTcUw+bTgBylGHeGHzTtBvuTXRS23dtwzFLl9tsgFM=
github.com/casvisor/casvisor-go-sdk v1.3.0 h1:HVgm2g3lWpNX2wBNidzR743QY4O5kAjLUJ9tS2juO8g=
github.com/casvisor/casvisor-go-sdk v1.3.0/go.mod h1:frnNtH5GA0wxzAQLyZxxfL0RSsSub9GQPi2Ybe86ocE=
github.com/casvisor/casvisor-go-sdk v1.4.0 h1:hbZEGGJ1cwdHFAxeXrMoNw6yha6Oyg2F0qQhBNCN/dg=
github.com/casvisor/casvisor-go-sdk v1.4.0/go.mod h1:frnNtH5GA0wxzAQLyZxxfL0RSsSub9GQPi2Ybe86ocE=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=

View File

@ -90,12 +90,18 @@ func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
Action: action,
Language: languageCode,
Object: object,
StatusCode: 200,
Response: fmt.Sprintf("{status:\"%s\", msg:\"%s\"}", resp.Status, resp.Msg),
IsTriggered: false,
}
return &record, nil
}
func addRecord(record *casvisorsdk.Record) (int64, error) {
affected, err := ormer.Engine.Insert(record)
return affected, err
}
func AddRecord(record *casvisorsdk.Record) bool {
if logPostOnly {
if record.Method == "GET" {
@ -108,7 +114,6 @@ func AddRecord(record *casvisorsdk.Record) bool {
}
record.Owner = record.Organization
record.Object = maskPassword(record.Object)
errWebhook := SendWebhooks(record)
@ -119,7 +124,7 @@ func AddRecord(record *casvisorsdk.Record) bool {
}
if casvisorsdk.GetClient() == nil {
affected, err := ormer.Engine.Insert(record)
affected, err := addRecord(record)
if err != nil {
panic(err)
}
@ -224,6 +229,40 @@ func getFilteredWebhooks(webhooks []*Webhook, organization string, action string
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 {
webhooks, err := getWebhooksByOrganization("")
if err != nil {
@ -248,11 +287,16 @@ func SendWebhooks(record *casvisorsdk.Record) error {
}
}
err = sendWebhook(webhook, record, user)
statusCode, respBody, err := sendWebhook(webhook, record, user)
if err != nil {
errs = append(errs, err)
continue
}
err = addWebhookRecord(webhook, record, statusCode, respBody, err)
if err != nil {
errs = append(errs, err)
}
}
if len(errs) > 0 {

View File

@ -15,6 +15,7 @@
package object
import (
"io"
"net/http"
"strings"
@ -22,7 +23,7 @@ import (
"github.com/casvisor/casvisor-go-sdk/casvisorsdk"
)
func sendWebhook(webhook *Webhook, record *casvisorsdk.Record, extendedUser *User) error {
func sendWebhook(webhook *Webhook, record *casvisorsdk.Record, extendedUser *User) (int, string, error) {
client := &http.Client{}
type RecordEx struct {
@ -38,7 +39,7 @@ func sendWebhook(webhook *Webhook, record *casvisorsdk.Record, extendedUser *Use
req, err := http.NewRequest(webhook.Method, webhook.Url, body)
if err != nil {
return err
return 0, "", err
}
req.Header.Set("Content-Type", webhook.ContentType)
@ -47,6 +48,15 @@ func sendWebhook(webhook *Webhook, record *casvisorsdk.Record, extendedUser *Use
req.Header.Set(header.Name, header.Value)
}
_, err = client.Do(req)
return err
resp, err := client.Do(req)
if err != nil {
return 0, "", err
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return 0, "", err
}
return resp.StatusCode, string(bodyBytes), err
}

View File

@ -151,6 +151,14 @@ class RecordListPage extends BaseListPage {
sorter: true,
...this.getColumnSearchProps("language"),
},
{
title: i18next.t("record:Status code"),
dataIndex: "statusCode",
key: "statusCode",
width: "90px",
sorter: true,
...this.getColumnSearchProps("statusCode"),
},
{
title: i18next.t("record:Response"),
dataIndex: "response",

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Kopiere den Link",
@ -1171,6 +1172,7 @@
"input password": "Eingabe des Passworts"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copiar enlace",
@ -1171,6 +1172,7 @@
"input password": "Ingresar contraseña"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copier le lien",
@ -1171,6 +1172,7 @@
"input password": "saisir le mot de passe"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Salin Tautan",
@ -1171,6 +1172,7 @@
"input password": "masukkan kata sandi"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "コピー リンク",
@ -1171,6 +1172,7 @@
"input password": "パスワードを入力してください"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "링크 복사하기",
@ -1171,6 +1172,7 @@
"input password": "비밀번호를 입력해주세요"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copiar Link",
@ -1171,6 +1172,7 @@
"input password": "Digite a senha"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Копировать ссылку",
@ -1171,6 +1172,7 @@
"input password": "введите пароль"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "input password"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Copy Link",
@ -1171,6 +1172,7 @@
"input password": "şifreyi girin"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -80,6 +80,7 @@
"Only signup": "Тільки реєстрація",
"Org choice mode": "Режим вибору організації",
"Org choice mode - Tooltip": "Режим вибору організації підказка",
"Please enable \\\"Signin session\\\" first before enabling \\\"Auto signin\\\"": "Please enable \\\"Signin session\\\" first before enabling \\\"Auto signin\\\"",
"Please input your application!": "Будь ласка, введіть свою заявку!",
"Please input your organization!": "Будь ласка, введіть вашу організацію!",
"Please select a HTML file": "Виберіть файл HTML",
@ -229,6 +230,7 @@
"Email": "Електронна пошта",
"Email - Tooltip": "Дійсна електронна пошта",
"Email only": "Лише електронна пошта",
"Email or Phone": "Email or Phone",
"Enable": "Увімкнути",
"Enable dark logo": "Увімкнути темний логотип",
"Enable dark logo - Tooltip": "Увімкнути темний логотип",
@ -311,6 +313,7 @@
"Phone": "Телефон",
"Phone - Tooltip": "Номер телефону",
"Phone only": "Тільки телефон",
"Phone or Email": "Phone or Email",
"Plan": "План",
"Plan - Tooltip": "План підказка",
"Plans": "Плани",
@ -391,6 +394,7 @@
"User type": "Тип користувача",
"User type - Tooltip": "Теги, до яких належить користувач, за умовчанням \"звичайний користувач\"",
"Users": "Користувачі",
"Users - Tooltip": "Users - Tooltip",
"Users under all organizations": "Користувачі в усіх організаціях",
"Verifications": "Перевірки",
"Webhooks": "Веб-хуки",
@ -473,7 +477,6 @@
"LDAP username, Email or phone": "Ім’я користувача LDAP, електронна пошта або телефон",
"Loading": "Завантаження",
"Logging out...": "Вихід...",
"Login button": "Кнопка входу",
"MetaMask plugin not detected": "Плагін MetaMask не виявлено",
"Model loading failure": "Помилка завантаження моделі",
"No account?": "Немає облікового запису?",
@ -498,6 +501,7 @@
"Sign in with Face ID": "Увійдіть за допомогою Face ID",
"Sign in with WebAuthn": "Увійдіть за допомогою WebAuthn",
"Sign in with {type}": "Увійдіть за допомогою {type}",
"Signin button": "Signin button",
"Signing in...": "Вхід...",
"Successfully logged in with WebAuthn credentials": "Успішно ввійшли за допомогою облікових даних WebAuthn",
"The camera is currently in use by another webpage": "Камера зараз використовується іншою веб-сторінкою",
@ -893,7 +897,8 @@
"record": {
"Is triggered": "Спрацьовує",
"Object": "Об'єкт",
"Response": "Відповідь"
"Response": "Відповідь",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Копіювати посилання",
@ -941,6 +946,7 @@
"Please select your country code!": "Виберіть код країни!",
"Please select your country/region!": "Виберіть свою країну/регіон!",
"Regex": "Регулярний вираз",
"Signup button": "Signup button",
"Terms of Use": "Умови використання",
"Terms of Use - Tooltip": "Умови використання, з якими користувачі повинні ознайомитися та погодитися під час реєстрації",
"Text 1": "Текст 1",
@ -1162,9 +1168,11 @@
"Values": "Цінності",
"Verification code sent": "Код підтвердження надіслано",
"WebAuthn credentials": "Облікові дані WebAuthn",
"You have changed the username, please save your change first before modifying the password": "You have changed the username, please save your change first before modifying the password",
"input password": "введіть пароль"
},
"verification": {
"Is used": "Is used",
"Receiver": "Приймач"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "Is triggered",
"Object": "Object",
"Response": "Response"
"Response": "Response",
"Status code": "Status code"
},
"resource": {
"Copy Link": "Sao chép liên kết",
@ -1171,6 +1172,7 @@
"input password": "Nhập mật khẩu"
},
"verification": {
"Is used": "Is used",
"Receiver": "Receiver"
},
"webhook": {

View File

@ -897,7 +897,8 @@
"record": {
"Is triggered": "是否触发",
"Object": "实体",
"Response": "响应"
"Response": "响应",
"Status code": "状态码"
},
"resource": {
"Copy Link": "复制链接",
@ -1171,6 +1172,7 @@
"input password": "输入密码"
},
"verification": {
"Is used": "已使用",
"Receiver": "接收者"
},
"webhook": {