feat(webhooks): add basic sending of webhooks

This commit is contained in:
kolaente 2023-09-14 11:16:07 +02:00
parent 7f3c300240
commit 7d1c5c50c5
Signed by untrusted user: konrad
GPG Key ID: F40E70337AB24C9B
2 changed files with 86 additions and 60 deletions

View File

@ -27,8 +27,8 @@ import (
// TaskCreatedEvent represents an event where a task has been created // TaskCreatedEvent represents an event where a task has been created
type TaskCreatedEvent struct { type TaskCreatedEvent struct {
Task *Task Task *Task `json:"task"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskCreatedEvent // Name defines the name for TaskCreatedEvent
@ -42,8 +42,8 @@ func (t *TaskCreatedEvent) ProjectID() int64 {
// TaskUpdatedEvent represents an event where a task has been updated // TaskUpdatedEvent represents an event where a task has been updated
type TaskUpdatedEvent struct { type TaskUpdatedEvent struct {
Task *Task Task *Task `json:"task"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskUpdatedEvent // Name defines the name for TaskUpdatedEvent
@ -57,8 +57,8 @@ func (t *TaskUpdatedEvent) ProjectID() int64 {
// TaskDeletedEvent represents a TaskDeletedEvent event // TaskDeletedEvent represents a TaskDeletedEvent event
type TaskDeletedEvent struct { type TaskDeletedEvent struct {
Task *Task Task *Task `json:"task"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskDeletedEvent // Name defines the name for TaskDeletedEvent
@ -72,9 +72,9 @@ func (t *TaskDeletedEvent) ProjectID() int64 {
// TaskAssigneeCreatedEvent represents an event where a task has been assigned to a user // TaskAssigneeCreatedEvent represents an event where a task has been assigned to a user
type TaskAssigneeCreatedEvent struct { type TaskAssigneeCreatedEvent struct {
Task *Task Task *Task `json:"task"`
Assignee *user.User Assignee *user.User `json:"assignee"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskAssigneeCreatedEvent // Name defines the name for TaskAssigneeCreatedEvent
@ -88,9 +88,9 @@ func (t *TaskAssigneeCreatedEvent) ProjectID() int64 {
// TaskAssigneeDeletedEvent represents a TaskAssigneeDeletedEvent event // TaskAssigneeDeletedEvent represents a TaskAssigneeDeletedEvent event
type TaskAssigneeDeletedEvent struct { type TaskAssigneeDeletedEvent struct {
Task *Task Task *Task `json:"task"`
Assignee *user.User Assignee *user.User `json:"assignee"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskAssigneeDeletedEvent // Name defines the name for TaskAssigneeDeletedEvent
@ -104,9 +104,9 @@ func (t *TaskAssigneeDeletedEvent) ProjectID() int64 {
// TaskCommentCreatedEvent represents an event where a task comment has been created // TaskCommentCreatedEvent represents an event where a task comment has been created
type TaskCommentCreatedEvent struct { type TaskCommentCreatedEvent struct {
Task *Task Task *Task `json:"task"`
Comment *TaskComment Comment *TaskComment `json:"comment"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskCommentCreatedEvent // Name defines the name for TaskCommentCreatedEvent
@ -120,9 +120,9 @@ func (t *TaskCommentCreatedEvent) ProjectID() int64 {
// TaskCommentUpdatedEvent represents a TaskCommentUpdatedEvent event // TaskCommentUpdatedEvent represents a TaskCommentUpdatedEvent event
type TaskCommentUpdatedEvent struct { type TaskCommentUpdatedEvent struct {
Task *Task Task *Task `json:"task"`
Comment *TaskComment Comment *TaskComment `json:"comment"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskCommentUpdatedEvent // Name defines the name for TaskCommentUpdatedEvent
@ -136,9 +136,9 @@ func (t *TaskCommentUpdatedEvent) ProjectID() int64 {
// TaskCommentDeletedEvent represents a TaskCommentDeletedEvent event // TaskCommentDeletedEvent represents a TaskCommentDeletedEvent event
type TaskCommentDeletedEvent struct { type TaskCommentDeletedEvent struct {
Task *Task Task *Task `json:"task"`
Comment *TaskComment Comment *TaskComment `json:"comment"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskCommentDeletedEvent // Name defines the name for TaskCommentDeletedEvent
@ -152,9 +152,9 @@ func (t *TaskCommentDeletedEvent) ProjectID() int64 {
// TaskAttachmentCreatedEvent represents a TaskAttachmentCreatedEvent event // TaskAttachmentCreatedEvent represents a TaskAttachmentCreatedEvent event
type TaskAttachmentCreatedEvent struct { type TaskAttachmentCreatedEvent struct {
Task *Task Task *Task `json:"task"`
Attachment *TaskAttachment Attachment *TaskAttachment `json:"attachment"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskAttachmentCreatedEvent // Name defines the name for TaskAttachmentCreatedEvent
@ -168,9 +168,9 @@ func (t *TaskAttachmentCreatedEvent) ProjectID() int64 {
// TaskAttachmentDeletedEvent represents a TaskAttachmentDeletedEvent event // TaskAttachmentDeletedEvent represents a TaskAttachmentDeletedEvent event
type TaskAttachmentDeletedEvent struct { type TaskAttachmentDeletedEvent struct {
Task *Task Task *Task `json:"task"`
Attachment *TaskAttachment Attachment *TaskAttachment `json:"attachment"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskAttachmentDeletedEvent // Name defines the name for TaskAttachmentDeletedEvent
@ -184,9 +184,9 @@ func (t *TaskAttachmentDeletedEvent) ProjectID() int64 {
// TaskRelationCreatedEvent represents a TaskRelationCreatedEvent event // TaskRelationCreatedEvent represents a TaskRelationCreatedEvent event
type TaskRelationCreatedEvent struct { type TaskRelationCreatedEvent struct {
Task *Task Task *Task `json:"task"`
Relation *TaskRelation Relation *TaskRelation `json:"relation"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskRelationCreatedEvent // Name defines the name for TaskRelationCreatedEvent
@ -200,9 +200,9 @@ func (t *TaskRelationCreatedEvent) ProjectID() int64 {
// TaskRelationDeletedEvent represents a TaskRelationDeletedEvent event // TaskRelationDeletedEvent represents a TaskRelationDeletedEvent event
type TaskRelationDeletedEvent struct { type TaskRelationDeletedEvent struct {
Task *Task Task *Task `json:"task"`
Relation *TaskRelation Relation *TaskRelation `json:"relation"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TaskRelationDeletedEvent // Name defines the name for TaskRelationDeletedEvent
@ -220,8 +220,8 @@ func (t *TaskRelationDeletedEvent) ProjectID() int64 {
// ProjectCreatedEvent represents an event where a project has been created // ProjectCreatedEvent represents an event where a project has been created
type ProjectCreatedEvent struct { type ProjectCreatedEvent struct {
Project *Project Project *Project `json:"project"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for ProjectCreatedEvent // Name defines the name for ProjectCreatedEvent
@ -231,8 +231,8 @@ func (l *ProjectCreatedEvent) Name() string {
// ProjectUpdatedEvent represents an event where a project has been updated // ProjectUpdatedEvent represents an event where a project has been updated
type ProjectUpdatedEvent struct { type ProjectUpdatedEvent struct {
Project *Project Project *Project `json:"project"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for ProjectUpdatedEvent // Name defines the name for ProjectUpdatedEvent
@ -246,8 +246,8 @@ func (p *ProjectUpdatedEvent) ProjectID() int64 {
// ProjectDeletedEvent represents an event where a project has been deleted // ProjectDeletedEvent represents an event where a project has been deleted
type ProjectDeletedEvent struct { type ProjectDeletedEvent struct {
Project *Project Project *Project `json:"project"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for ProjectDeletedEvent // Name defines the name for ProjectDeletedEvent
@ -265,9 +265,9 @@ func (p *ProjectDeletedEvent) ProjectID() int64 {
// ProjectSharedWithUserEvent represents an event where a project has been shared with a user // ProjectSharedWithUserEvent represents an event where a project has been shared with a user
type ProjectSharedWithUserEvent struct { type ProjectSharedWithUserEvent struct {
Project *Project Project *Project `json:"project"`
User *user.User User *user.User `json:"user"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for ProjectSharedWithUserEvent // Name defines the name for ProjectSharedWithUserEvent
@ -281,9 +281,9 @@ func (p *ProjectSharedWithUserEvent) ProjectID() int64 {
// ProjectSharedWithTeamEvent represents an event where a project has been shared with a team // ProjectSharedWithTeamEvent represents an event where a project has been shared with a team
type ProjectSharedWithTeamEvent struct { type ProjectSharedWithTeamEvent struct {
Project *Project Project *Project `json:"project"`
Team *Team Team *Team `json:"team"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for ProjectSharedWithTeamEvent // Name defines the name for ProjectSharedWithTeamEvent
@ -301,9 +301,9 @@ func (p *ProjectSharedWithTeamEvent) ProjectID() int64 {
// TeamMemberAddedEvent defines an event where a user is added to a team // TeamMemberAddedEvent defines an event where a user is added to a team
type TeamMemberAddedEvent struct { type TeamMemberAddedEvent struct {
Team *Team Team *Team `json:"team"`
Member *user.User Member *user.User `json:"member"`
Doer *user.User Doer *user.User `json:"doer"`
} }
// Name defines the name for TeamMemberAddedEvent // Name defines the name for TeamMemberAddedEvent
@ -313,8 +313,8 @@ func (t *TeamMemberAddedEvent) Name() string {
// TeamCreatedEvent represents a TeamCreatedEvent event // TeamCreatedEvent represents a TeamCreatedEvent event
type TeamCreatedEvent struct { type TeamCreatedEvent struct {
Team *Team Team *Team `json:"team"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for TeamCreatedEvent // Name defines the name for TeamCreatedEvent
@ -324,8 +324,8 @@ func (t *TeamCreatedEvent) Name() string {
// TeamDeletedEvent represents a TeamDeletedEvent event // TeamDeletedEvent represents a TeamDeletedEvent event
type TeamDeletedEvent struct { type TeamDeletedEvent struct {
Team *Team Team *Team `json:"team"`
Doer web.Auth Doer web.Auth `json:"doer"`
} }
// Name defines the name for TeamDeletedEvent // Name defines the name for TeamDeletedEvent
@ -335,7 +335,7 @@ func (t *TeamDeletedEvent) Name() string {
// UserDataExportRequestedEvent represents a UserDataExportRequestedEvent event // UserDataExportRequestedEvent represents a UserDataExportRequestedEvent event
type UserDataExportRequestedEvent struct { type UserDataExportRequestedEvent struct {
User *user.User User *user.User `json:"user"`
} }
// Name defines the name for UserDataExportRequestedEvent // Name defines the name for UserDataExportRequestedEvent

View File

@ -639,24 +639,43 @@ func (wl *WebhookListener) Name() string {
} }
type WebhookPayload struct { type WebhookPayload struct {
EventName string `json:"event_name"` EventName string `json:"event_name"`
Time time.Time `json:"time"` Time time.Time `json:"time"`
Data WebhookEvent `json:"data"` Data interface{} `json:"data"`
}
func getProjectIDFromAnyEvent(eventPayload map[string]interface{}) int64 {
if task, has := eventPayload["task"]; has {
t := task.(map[string]interface{})
if projectID, has := t["project_id"]; has {
switch projectID.(type) {
case int64:
return projectID.(int64)
case float64:
return int64(projectID.(float64))
}
return projectID.(int64)
}
}
return 0
} }
// Handle is executed when the event WebhookListener listens on is fired // Handle is executed when the event WebhookListener listens on is fired
func (wl *WebhookListener) Handle(msg *message.Message) (err error) { func (wl *WebhookListener) Handle(msg *message.Message) (err error) {
var event WebhookEvent var event map[string]interface{}
err = json.Unmarshal(msg.Payload, event) err = json.Unmarshal(msg.Payload, &event)
if err != nil { if err != nil {
return err return err
} }
projectID := getProjectIDFromAnyEvent(event)
s := db.NewSession() s := db.NewSession()
defer s.Close() defer s.Close()
ws := []*Webhook{} ws := []*Webhook{}
err = s.Where("project_id = ?", event.ProjectID()). err = s.Where("project_id = ?", projectID).
Find(&ws) Find(&ws)
if err != nil { if err != nil {
return err return err
@ -685,7 +704,14 @@ func (wl *WebhookListener) Handle(msg *message.Message) (err error) {
if err != nil { if err != nil {
return err return err
} }
_, err = http.NewRequest(http.MethodPost, webhook.TargetURL, bytes.NewReader(payload)) req, err := http.NewRequest(http.MethodPost, webhook.TargetURL, bytes.NewReader(payload))
if err != nil {
return err
}
_, err = http.DefaultClient.Do(req)
if err == nil {
log.Debugf("Sent webhook payload for webhook %d for event %s", webhook.ID, wl.EventName)
}
return return
} }