2014-05-06 04:52:25 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2017-05-29 10:17:15 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2014-05-06 04:52:25 +04:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"encoding/json"
2015-08-27 18:06:14 +03:00
"fmt"
2014-06-08 12:45:34 +04:00
"time"
2014-05-06 04:52:25 +04:00
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2019-05-11 13:21:34 +03:00
api "code.gitea.io/gitea/modules/structs"
2019-08-15 17:46:21 +03:00
"code.gitea.io/gitea/modules/timeutil"
2017-08-28 08:06:45 +03:00
gouuid "github.com/satori/go.uuid"
2014-05-06 04:52:25 +04:00
)
2016-11-22 09:42:52 +03:00
// HookContentType is the content type of a web hook
2014-06-08 12:45:34 +04:00
type HookContentType int
2014-05-06 04:52:25 +04:00
const (
2016-11-22 09:42:52 +03:00
// ContentTypeJSON is a JSON payload for web hooks
2016-11-07 23:58:22 +03:00
ContentTypeJSON HookContentType = iota + 1
2016-11-22 09:42:52 +03:00
// ContentTypeForm is an url-encoded form payload for web hook
2016-11-07 19:53:22 +03:00
ContentTypeForm
2014-05-06 04:52:25 +04:00
)
2014-11-13 20:57:00 +03:00
var hookContentTypes = map [ string ] HookContentType {
2016-11-07 23:58:22 +03:00
"json" : ContentTypeJSON ,
2016-11-07 19:53:22 +03:00
"form" : ContentTypeForm ,
2014-11-13 20:57:00 +03:00
}
// ToHookContentType returns HookContentType by given name.
func ToHookContentType ( name string ) HookContentType {
return hookContentTypes [ name ]
}
2016-11-22 09:42:52 +03:00
// Name returns the name of a given web hook's content type
2014-11-13 10:32:18 +03:00
func ( t HookContentType ) Name ( ) string {
switch t {
2016-11-07 23:58:22 +03:00
case ContentTypeJSON :
2014-11-13 10:32:18 +03:00
return "json"
2016-11-07 19:53:22 +03:00
case ContentTypeForm :
2014-11-13 10:32:18 +03:00
return "form"
}
return ""
}
2014-11-13 20:57:00 +03:00
// IsValidHookContentType returns true if given name is a valid hook content type.
func IsValidHookContentType ( name string ) bool {
_ , ok := hookContentTypes [ name ]
return ok
}
2016-11-22 09:42:52 +03:00
// HookEvents is a set of web hook events
2015-08-28 18:36:13 +03:00
type HookEvents struct {
2020-03-06 08:10:48 +03:00
Create bool ` json:"create" `
Delete bool ` json:"delete" `
Fork bool ` json:"fork" `
Issues bool ` json:"issues" `
IssueAssign bool ` json:"issue_assign" `
IssueLabel bool ` json:"issue_label" `
IssueMilestone bool ` json:"issue_milestone" `
IssueComment bool ` json:"issue_comment" `
Push bool ` json:"push" `
PullRequest bool ` json:"pull_request" `
PullRequestAssign bool ` json:"pull_request_assign" `
PullRequestLabel bool ` json:"pull_request_label" `
PullRequestMilestone bool ` json:"pull_request_milestone" `
PullRequestComment bool ` json:"pull_request_comment" `
PullRequestReview bool ` json:"pull_request_review" `
PullRequestSync bool ` json:"pull_request_sync" `
Repository bool ` json:"repository" `
Release bool ` json:"release" `
2015-08-28 18:36:13 +03:00
}
2014-06-08 12:45:34 +04:00
// HookEvent represents events that will delivery hook.
2014-05-06 04:52:25 +04:00
type HookEvent struct {
2019-09-09 08:48:21 +03:00
PushOnly bool ` json:"push_only" `
SendEverything bool ` json:"send_everything" `
ChooseEvents bool ` json:"choose_events" `
BranchFilter string ` json:"branch_filter" `
2015-08-28 18:36:13 +03:00
HookEvents ` json:"events" `
2014-05-06 04:52:25 +04:00
}
2016-11-22 09:42:52 +03:00
// HookStatus is the status of a web hook
2015-08-26 16:45:51 +03:00
type HookStatus int
2016-11-22 09:42:52 +03:00
// Possible statuses of a web hook
2015-08-26 16:45:51 +03:00
const (
2016-11-07 19:08:21 +03:00
HookStatusNone = iota
2016-11-07 18:37:32 +03:00
HookStatusSucceed
HookStatusFail
2015-08-26 16:45:51 +03:00
)
2014-06-08 12:45:34 +04:00
// Webhook represents a web hook object.
2014-05-06 04:52:25 +04:00
type Webhook struct {
2020-03-09 01:08:05 +03:00
ID int64 ` xorm:"pk autoincr" `
RepoID int64 ` xorm:"INDEX" ` // An ID of 0 indicates either a default or system webhook
OrgID int64 ` xorm:"INDEX" `
IsSystemWebhook bool
URL string ` xorm:"url TEXT" `
Signature string ` xorm:"TEXT" `
HTTPMethod string ` xorm:"http_method" `
ContentType HookContentType
Secret string ` xorm:"TEXT" `
Events string ` xorm:"TEXT" `
* HookEvent ` xorm:"-" `
IsSSL bool ` xorm:"is_ssl" `
IsActive bool ` xorm:"INDEX" `
HookTaskType HookTaskType
Meta string ` xorm:"TEXT" ` // store hook-specific attributes
LastStatus HookStatus // Last delivery status
2016-03-10 03:53:30 +03:00
2019-08-15 17:46:21 +03:00
CreatedUnix timeutil . TimeStamp ` xorm:"INDEX created" `
UpdatedUnix timeutil . TimeStamp ` xorm:"INDEX updated" `
2014-05-06 04:52:25 +04:00
}
2017-10-01 19:52:35 +03:00
// AfterLoad updates the webhook object upon setting a column
func ( w * Webhook ) AfterLoad ( ) {
w . HookEvent = & HookEvent { }
if err := json . Unmarshal ( [ ] byte ( w . Events ) , w . HookEvent ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Unmarshal[%d]: %v" , w . ID , err )
2014-05-06 04:52:25 +04:00
}
}
2015-08-27 18:06:14 +03:00
// History returns history of webhook by given conditions.
func ( w * Webhook ) History ( page int ) ( [ ] * HookTask , error ) {
return HookTasks ( w . ID , page )
}
2014-06-08 12:54:52 +04:00
// UpdateEvent handles conversion from HookEvent to Events.
2014-06-08 12:45:34 +04:00
func ( w * Webhook ) UpdateEvent ( ) error {
2014-05-06 05:36:08 +04:00
data , err := json . Marshal ( w . HookEvent )
2014-05-06 04:52:25 +04:00
w . Events = string ( data )
return err
}
2015-08-28 18:36:13 +03:00
// HasCreateEvent returns true if hook enabled create event.
func ( w * Webhook ) HasCreateEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Create )
}
2018-05-16 17:01:55 +03:00
// HasDeleteEvent returns true if hook enabled delete event.
func ( w * Webhook ) HasDeleteEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Delete )
}
// HasForkEvent returns true if hook enabled fork event.
func ( w * Webhook ) HasForkEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Fork )
}
// HasIssuesEvent returns true if hook enabled issues event.
func ( w * Webhook ) HasIssuesEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Issues )
}
2020-03-06 08:10:48 +03:00
// HasIssuesAssignEvent returns true if hook enabled issues assign event.
func ( w * Webhook ) HasIssuesAssignEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . IssueAssign )
}
// HasIssuesLabelEvent returns true if hook enabled issues label event.
func ( w * Webhook ) HasIssuesLabelEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . IssueLabel )
}
// HasIssuesMilestoneEvent returns true if hook enabled issues milestone event.
func ( w * Webhook ) HasIssuesMilestoneEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . IssueMilestone )
}
2018-05-16 17:01:55 +03:00
// HasIssueCommentEvent returns true if hook enabled issue_comment event.
func ( w * Webhook ) HasIssueCommentEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . IssueComment )
}
2014-12-07 04:22:48 +03:00
// HasPushEvent returns true if hook enabled push event.
2014-05-06 19:50:31 +04:00
func ( w * Webhook ) HasPushEvent ( ) bool {
2015-08-28 18:36:13 +03:00
return w . PushOnly || w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Push )
2014-05-06 19:50:31 +04:00
}
2016-08-14 13:32:24 +03:00
// HasPullRequestEvent returns true if hook enabled pull request event.
func ( w * Webhook ) HasPullRequestEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequest )
}
2020-03-06 08:10:48 +03:00
// HasPullRequestAssignEvent returns true if hook enabled pull request assign event.
func ( w * Webhook ) HasPullRequestAssignEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestAssign )
}
// HasPullRequestLabelEvent returns true if hook enabled pull request label event.
func ( w * Webhook ) HasPullRequestLabelEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestLabel )
}
// HasPullRequestMilestoneEvent returns true if hook enabled pull request milestone event.
func ( w * Webhook ) HasPullRequestMilestoneEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestMilestone )
}
// HasPullRequestCommentEvent returns true if hook enabled pull_request_comment event.
func ( w * Webhook ) HasPullRequestCommentEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestComment )
}
// HasPullRequestApprovedEvent returns true if hook enabled pull request review event.
func ( w * Webhook ) HasPullRequestApprovedEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestReview )
}
// HasPullRequestRejectedEvent returns true if hook enabled pull request review event.
func ( w * Webhook ) HasPullRequestRejectedEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestReview )
}
// HasPullRequestReviewCommentEvent returns true if hook enabled pull request review event.
func ( w * Webhook ) HasPullRequestReviewCommentEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestReview )
}
// HasPullRequestSyncEvent returns true if hook enabled pull request sync event.
func ( w * Webhook ) HasPullRequestSyncEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . PullRequestSync )
}
2018-05-16 17:01:55 +03:00
// HasReleaseEvent returns if hook enabled release event.
func ( w * Webhook ) HasReleaseEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Release )
}
2017-09-03 11:20:24 +03:00
// HasRepositoryEvent returns if hook enabled repository event.
func ( w * Webhook ) HasRepositoryEvent ( ) bool {
return w . SendEverything ||
( w . ChooseEvents && w . HookEvents . Repository )
}
2019-11-02 01:51:22 +03:00
// EventCheckers returns event checkers
func ( w * Webhook ) EventCheckers ( ) [ ] struct {
Has func ( ) bool
Type HookEventType
2018-05-16 17:01:55 +03:00
} {
return [ ] struct {
2019-11-02 01:51:22 +03:00
Has func ( ) bool
Type HookEventType
2018-05-16 17:01:55 +03:00
} {
{ w . HasCreateEvent , HookEventCreate } ,
{ w . HasDeleteEvent , HookEventDelete } ,
{ w . HasForkEvent , HookEventFork } ,
{ w . HasPushEvent , HookEventPush } ,
{ w . HasIssuesEvent , HookEventIssues } ,
2020-03-06 08:10:48 +03:00
{ w . HasIssuesAssignEvent , HookEventIssueAssign } ,
{ w . HasIssuesLabelEvent , HookEventIssueLabel } ,
{ w . HasIssuesMilestoneEvent , HookEventIssueMilestone } ,
2018-05-16 17:01:55 +03:00
{ w . HasIssueCommentEvent , HookEventIssueComment } ,
{ w . HasPullRequestEvent , HookEventPullRequest } ,
2020-03-06 08:10:48 +03:00
{ w . HasPullRequestAssignEvent , HookEventPullRequestAssign } ,
{ w . HasPullRequestLabelEvent , HookEventPullRequestLabel } ,
{ w . HasPullRequestMilestoneEvent , HookEventPullRequestMilestone } ,
{ w . HasPullRequestCommentEvent , HookEventPullRequestComment } ,
{ w . HasPullRequestApprovedEvent , HookEventPullRequestReviewApproved } ,
{ w . HasPullRequestRejectedEvent , HookEventPullRequestReviewRejected } ,
{ w . HasPullRequestCommentEvent , HookEventPullRequestReviewComment } ,
{ w . HasPullRequestSyncEvent , HookEventPullRequestSync } ,
2018-05-16 17:01:55 +03:00
{ w . HasRepositoryEvent , HookEventRepository } ,
{ w . HasReleaseEvent , HookEventRelease } ,
}
}
2016-11-22 09:42:52 +03:00
// EventsArray returns an array of hook events
2015-08-29 06:49:59 +03:00
func ( w * Webhook ) EventsArray ( ) [ ] string {
2018-05-16 17:01:55 +03:00
events := make ( [ ] string , 0 , 7 )
2019-11-02 01:51:22 +03:00
for _ , c := range w . EventCheckers ( ) {
if c . Has ( ) {
events = append ( events , string ( c . Type ) )
2018-05-16 17:01:55 +03:00
}
2016-08-25 06:44:58 +03:00
}
2015-08-29 06:49:59 +03:00
return events
}
2014-06-08 12:45:34 +04:00
// CreateWebhook creates a new web hook.
2014-05-06 04:52:25 +04:00
func CreateWebhook ( w * Webhook ) error {
2019-03-19 05:33:20 +03:00
return createWebhook ( x , w )
}
func createWebhook ( e Engine , w * Webhook ) error {
_ , err := e . Insert ( w )
2014-05-06 04:52:25 +04:00
return err
}
2016-07-17 03:33:59 +03:00
// getWebhook uses argument bean as query condition,
// ID must be specified and do not assign unnecessary fields.
func getWebhook ( bean * Webhook ) ( * Webhook , error ) {
has , err := x . Get ( bean )
2014-05-06 05:36:08 +04:00
if err != nil {
return nil , err
} else if ! has {
2016-07-17 03:33:59 +03:00
return nil , ErrWebhookNotExist { bean . ID }
2014-05-06 05:36:08 +04:00
}
2016-07-17 03:33:59 +03:00
return bean , nil
}
2017-08-30 08:36:52 +03:00
// GetWebhookByID returns webhook of repository by given ID.
func GetWebhookByID ( id int64 ) ( * Webhook , error ) {
return getWebhook ( & Webhook {
ID : id ,
} )
}
2016-07-17 03:33:59 +03:00
// GetWebhookByRepoID returns webhook of repository by given ID.
func GetWebhookByRepoID ( repoID , id int64 ) ( * Webhook , error ) {
return getWebhook ( & Webhook {
ID : id ,
RepoID : repoID ,
} )
2014-05-06 05:36:08 +04:00
}
2016-07-15 20:02:55 +03:00
// GetWebhookByOrgID returns webhook of organization by given ID.
func GetWebhookByOrgID ( orgID , id int64 ) ( * Webhook , error ) {
2016-07-17 03:33:59 +03:00
return getWebhook ( & Webhook {
ID : id ,
OrgID : orgID ,
} )
2016-07-15 20:02:55 +03:00
}
2015-08-28 18:36:13 +03:00
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
2016-08-25 02:05:56 +03:00
func GetActiveWebhooksByRepoID ( repoID int64 ) ( [ ] * Webhook , error ) {
2017-09-03 11:20:24 +03:00
return getActiveWebhooksByRepoID ( x , repoID )
}
func getActiveWebhooksByRepoID ( e Engine , repoID int64 ) ( [ ] * Webhook , error ) {
2016-08-25 02:05:56 +03:00
webhooks := make ( [ ] * Webhook , 0 , 5 )
2017-09-03 11:20:24 +03:00
return webhooks , e . Where ( "is_active=?" , true ) .
2017-01-25 13:37:35 +03:00
Find ( & webhooks , & Webhook { RepoID : repoID } )
2014-05-06 19:50:31 +04:00
}
2016-08-25 02:05:56 +03:00
// GetWebhooksByRepoID returns all webhooks of a repository.
2020-01-24 22:00:29 +03:00
func GetWebhooksByRepoID ( repoID int64 , listOptions ListOptions ) ( [ ] * Webhook , error ) {
if listOptions . Page == 0 {
webhooks := make ( [ ] * Webhook , 0 , 5 )
return webhooks , x . Find ( & webhooks , & Webhook { RepoID : repoID } )
}
sess := listOptions . getPaginatedSession ( )
webhooks := make ( [ ] * Webhook , 0 , listOptions . PageSize )
return webhooks , sess . Find ( & webhooks , & Webhook { RepoID : repoID } )
2014-05-06 04:52:25 +04:00
}
2014-05-06 05:36:08 +04:00
2017-01-25 13:37:35 +03:00
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
func GetActiveWebhooksByOrgID ( orgID int64 ) ( ws [ ] * Webhook , err error ) {
2017-09-03 11:20:24 +03:00
return getActiveWebhooksByOrgID ( x , orgID )
}
func getActiveWebhooksByOrgID ( e Engine , orgID int64 ) ( ws [ ] * Webhook , err error ) {
err = e .
2017-01-25 13:37:35 +03:00
Where ( "org_id=?" , orgID ) .
And ( "is_active=?" , true ) .
Find ( & ws )
return ws , err
}
2020-01-24 22:00:29 +03:00
// GetWebhooksByOrgID returns paginated webhooks for an organization.
func GetWebhooksByOrgID ( orgID int64 , listOptions ListOptions ) ( [ ] * Webhook , error ) {
if listOptions . Page == 0 {
ws := make ( [ ] * Webhook , 0 , 5 )
return ws , x . Find ( & ws , & Webhook { OrgID : orgID } )
}
sess := listOptions . getPaginatedSession ( )
ws := make ( [ ] * Webhook , 0 , listOptions . PageSize )
return ws , sess . Find ( & ws , & Webhook { OrgID : orgID } )
2017-01-25 13:37:35 +03:00
}
2019-03-19 05:33:20 +03:00
// GetDefaultWebhook returns admin-default webhook by given ID.
func GetDefaultWebhook ( id int64 ) ( * Webhook , error ) {
webhook := & Webhook { ID : id }
has , err := x .
2020-03-09 01:08:05 +03:00
Where ( "repo_id=? AND org_id=? AND is_system_webhook=?" , 0 , 0 , false ) .
2019-03-19 05:33:20 +03:00
Get ( webhook )
if err != nil {
return nil , err
} else if ! has {
return nil , ErrWebhookNotExist { id }
}
return webhook , nil
}
// GetDefaultWebhooks returns all admin-default webhooks.
func GetDefaultWebhooks ( ) ( [ ] * Webhook , error ) {
return getDefaultWebhooks ( x )
}
func getDefaultWebhooks ( e Engine ) ( [ ] * Webhook , error ) {
webhooks := make ( [ ] * Webhook , 0 , 5 )
return webhooks , e .
2020-03-09 01:08:05 +03:00
Where ( "repo_id=? AND org_id=? AND is_system_webhook=?" , 0 , 0 , false ) .
Find ( & webhooks )
}
// GetSystemWebhook returns admin system webhook by given ID.
func GetSystemWebhook ( id int64 ) ( * Webhook , error ) {
webhook := & Webhook { ID : id }
has , err := x .
Where ( "repo_id=? AND org_id=? AND is_system_webhook=?" , 0 , 0 , true ) .
Get ( webhook )
if err != nil {
return nil , err
} else if ! has {
return nil , ErrWebhookNotExist { id }
}
return webhook , nil
}
// GetSystemWebhooks returns all admin system webhooks.
func GetSystemWebhooks ( ) ( [ ] * Webhook , error ) {
return getSystemWebhooks ( x )
}
func getSystemWebhooks ( e Engine ) ( [ ] * Webhook , error ) {
webhooks := make ( [ ] * Webhook , 0 , 5 )
return webhooks , e .
Where ( "repo_id=? AND org_id=? AND is_system_webhook=?" , 0 , 0 , true ) .
2019-03-19 05:33:20 +03:00
Find ( & webhooks )
}
2014-06-08 12:45:34 +04:00
// UpdateWebhook updates information of webhook.
func UpdateWebhook ( w * Webhook ) error {
2017-10-05 07:43:04 +03:00
_ , err := x . ID ( w . ID ) . AllCols ( ) . Update ( w )
2014-06-08 12:45:34 +04:00
return err
}
2017-08-30 08:36:52 +03:00
// UpdateWebhookLastStatus updates last status of webhook.
func UpdateWebhookLastStatus ( w * Webhook ) error {
_ , err := x . ID ( w . ID ) . Cols ( "last_status" ) . Update ( w )
return err
}
2016-07-17 03:33:59 +03:00
// deleteWebhook uses argument bean as query condition,
// ID must be specified and do not assign unnecessary fields.
func deleteWebhook ( bean * Webhook ) ( err error ) {
2015-08-26 16:45:51 +03:00
sess := x . NewSession ( )
2017-06-21 03:57:05 +03:00
defer sess . Close ( )
2015-08-26 16:45:51 +03:00
if err = sess . Begin ( ) ; err != nil {
return err
}
2017-01-14 05:14:48 +03:00
if count , err := sess . Delete ( bean ) ; err != nil {
2015-08-26 16:45:51 +03:00
return err
2017-01-14 05:14:48 +03:00
} else if count == 0 {
return ErrWebhookNotExist { ID : bean . ID }
2016-07-17 03:33:59 +03:00
} else if _ , err = sess . Delete ( & HookTask { HookID : bean . ID } ) ; err != nil {
2015-08-26 16:45:51 +03:00
return err
}
return sess . Commit ( )
2014-05-06 05:36:08 +04:00
}
2014-06-08 12:45:34 +04:00
2016-07-17 03:33:59 +03:00
// DeleteWebhookByRepoID deletes webhook of repository by given ID.
2016-07-23 15:24:44 +03:00
func DeleteWebhookByRepoID ( repoID , id int64 ) error {
2016-07-17 03:33:59 +03:00
return deleteWebhook ( & Webhook {
ID : id ,
RepoID : repoID ,
} )
}
// DeleteWebhookByOrgID deletes webhook of organization by given ID.
2016-07-23 15:24:44 +03:00
func DeleteWebhookByOrgID ( orgID , id int64 ) error {
2016-07-17 03:33:59 +03:00
return deleteWebhook ( & Webhook {
ID : id ,
OrgID : orgID ,
} )
}
2020-03-09 01:08:05 +03:00
// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
func DeleteDefaultSystemWebhook ( id int64 ) error {
2019-03-19 05:33:20 +03:00
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return err
}
count , err := sess .
Where ( "repo_id=? AND org_id=?" , 0 , 0 ) .
Delete ( & Webhook { ID : id } )
if err != nil {
return err
} else if count == 0 {
return ErrWebhookNotExist { ID : id }
}
if _ , err := sess . Delete ( & HookTask { HookID : id } ) ; err != nil {
return err
}
return sess . Commit ( )
}
// copyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
func copyDefaultWebhooksToRepo ( e Engine , repoID int64 ) error {
ws , err := getDefaultWebhooks ( e )
if err != nil {
return fmt . Errorf ( "GetDefaultWebhooks: %v" , err )
}
for _ , w := range ws {
w . ID = 0
w . RepoID = repoID
if err := createWebhook ( e , w ) ; err != nil {
return fmt . Errorf ( "CreateWebhook: %v" , err )
}
}
return nil
}
2014-06-08 12:45:34 +04:00
// ___ ___ __ ___________ __
// / | \ ____ ____ | | _\__ ___/____ _____| | __
// / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ /
// \ Y ( <_> | <_> ) < | | / __ \_\___ \| <
// \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \
// \/ \/ \/ \/ \/
2016-11-22 09:42:52 +03:00
// HookTaskType is the type of an hook task
2014-06-08 12:45:34 +04:00
type HookTaskType int
2016-11-22 09:42:52 +03:00
// Types of hook tasks
2014-06-08 12:45:34 +04:00
const (
2014-08-24 16:59:47 +04:00
GOGS HookTaskType = iota + 1
SLACK
2017-05-29 10:17:15 +03:00
GITEA
2017-08-28 08:06:45 +03:00
DISCORD
2017-11-21 07:26:43 +03:00
DINGTALK
2019-04-19 05:45:02 +03:00
TELEGRAM
2019-04-19 17:18:06 +03:00
MSTEAMS
2020-02-12 11:48:28 +03:00
FEISHU
2020-03-28 16:09:55 +03:00
MATRIX
2014-06-08 12:45:34 +04:00
)
2014-11-13 20:57:00 +03:00
var hookTaskTypes = map [ string ] HookTaskType {
2017-11-21 07:26:43 +03:00
"gitea" : GITEA ,
"gogs" : GOGS ,
"slack" : SLACK ,
"discord" : DISCORD ,
"dingtalk" : DINGTALK ,
2019-04-19 05:45:02 +03:00
"telegram" : TELEGRAM ,
2019-04-19 17:18:06 +03:00
"msteams" : MSTEAMS ,
2020-02-12 11:48:28 +03:00
"feishu" : FEISHU ,
2020-03-28 16:09:55 +03:00
"matrix" : MATRIX ,
2014-11-13 20:57:00 +03:00
}
// ToHookTaskType returns HookTaskType by given name.
func ToHookTaskType ( name string ) HookTaskType {
return hookTaskTypes [ name ]
}
2016-11-22 09:42:52 +03:00
// Name returns the name of an hook task type
2014-11-13 10:32:18 +03:00
func ( t HookTaskType ) Name ( ) string {
switch t {
2017-05-29 10:17:15 +03:00
case GITEA :
return "gitea"
2014-11-13 10:32:18 +03:00
case GOGS :
return "gogs"
case SLACK :
return "slack"
2017-08-28 08:06:45 +03:00
case DISCORD :
return "discord"
2017-11-21 07:26:43 +03:00
case DINGTALK :
return "dingtalk"
2019-04-19 05:45:02 +03:00
case TELEGRAM :
return "telegram"
2019-04-19 17:18:06 +03:00
case MSTEAMS :
return "msteams"
2020-02-12 11:48:28 +03:00
case FEISHU :
return "feishu"
2020-03-28 16:09:55 +03:00
case MATRIX :
return "matrix"
2014-11-13 10:32:18 +03:00
}
return ""
}
2014-11-13 20:57:00 +03:00
// IsValidHookTaskType returns true if given name is a valid hook task type.
func IsValidHookTaskType ( name string ) bool {
_ , ok := hookTaskTypes [ name ]
return ok
}
2016-11-22 09:42:52 +03:00
// HookEventType is the type of an hook event
2014-08-10 02:40:10 +04:00
type HookEventType string
2016-11-22 09:42:52 +03:00
// Types of hook events
2014-08-10 02:40:10 +04:00
const (
2020-03-06 08:10:48 +03:00
HookEventCreate HookEventType = "create"
HookEventDelete HookEventType = "delete"
HookEventFork HookEventType = "fork"
HookEventPush HookEventType = "push"
HookEventIssues HookEventType = "issues"
HookEventIssueAssign HookEventType = "issue_assign"
HookEventIssueLabel HookEventType = "issue_label"
HookEventIssueMilestone HookEventType = "issue_milestone"
HookEventIssueComment HookEventType = "issue_comment"
HookEventPullRequest HookEventType = "pull_request"
HookEventPullRequestAssign HookEventType = "pull_request_assign"
HookEventPullRequestLabel HookEventType = "pull_request_label"
HookEventPullRequestMilestone HookEventType = "pull_request_milestone"
HookEventPullRequestComment HookEventType = "pull_request_comment"
HookEventPullRequestReviewApproved HookEventType = "pull_request_review_approved"
HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment"
HookEventPullRequestSync HookEventType = "pull_request_sync"
HookEventRepository HookEventType = "repository"
HookEventRelease HookEventType = "release"
2014-08-10 02:40:10 +04:00
)
2020-03-06 08:10:48 +03:00
// Event returns the HookEventType as an event string
func ( h HookEventType ) Event ( ) string {
switch h {
case HookEventCreate :
return "create"
case HookEventDelete :
return "delete"
case HookEventFork :
return "fork"
case HookEventPush :
return "push"
case HookEventIssues , HookEventIssueAssign , HookEventIssueLabel , HookEventIssueMilestone :
return "issues"
case HookEventPullRequest , HookEventPullRequestAssign , HookEventPullRequestLabel , HookEventPullRequestMilestone ,
HookEventPullRequestSync :
return "pull_request"
case HookEventIssueComment , HookEventPullRequestComment :
return "issue_comment"
case HookEventPullRequestReviewApproved :
return "pull_request_approved"
case HookEventPullRequestReviewRejected :
return "pull_request_rejected"
case HookEventPullRequestReviewComment :
return "pull_request_comment"
case HookEventRepository :
return "repository"
case HookEventRelease :
return "release"
}
return ""
}
2015-08-27 18:06:14 +03:00
// HookRequest represents hook task request information.
type HookRequest struct {
Headers map [ string ] string ` json:"headers" `
}
// HookResponse represents hook task response information.
type HookResponse struct {
Status int ` json:"status" `
Headers map [ string ] string ` json:"headers" `
Body string ` json:"body" `
}
2014-06-08 12:54:52 +04:00
// HookTask represents a hook task.
2014-06-08 12:45:34 +04:00
type HookTask struct {
2015-08-27 18:06:14 +03:00
ID int64 ` xorm:"pk autoincr" `
RepoID int64 ` xorm:"INDEX" `
HookID int64
UUID string
Type HookTaskType
2016-01-27 03:38:07 +03:00
URL string ` xorm:"TEXT" `
2019-03-26 03:08:55 +03:00
Signature string ` xorm:"TEXT" `
2015-08-28 18:36:13 +03:00
api . Payloader ` xorm:"-" `
2015-08-27 18:06:14 +03:00
PayloadContent string ` xorm:"TEXT" `
2019-05-05 21:09:02 +03:00
HTTPMethod string ` xorm:"http_method" `
2015-08-27 18:06:14 +03:00
ContentType HookContentType
EventType HookEventType
IsSSL bool
IsDelivered bool
Delivered int64
DeliveredString string ` xorm:"-" `
// History info.
IsSucceed bool
RequestContent string ` xorm:"TEXT" `
RequestInfo * HookRequest ` xorm:"-" `
ResponseContent string ` xorm:"TEXT" `
ResponseInfo * HookResponse ` xorm:"-" `
}
2016-11-22 09:42:52 +03:00
// BeforeUpdate will be invoked by XORM before updating a record
// representing this object
2015-08-27 18:06:14 +03:00
func ( t * HookTask ) BeforeUpdate ( ) {
if t . RequestInfo != nil {
2016-11-22 09:42:52 +03:00
t . RequestContent = t . simpleMarshalJSON ( t . RequestInfo )
2015-08-27 18:06:14 +03:00
}
if t . ResponseInfo != nil {
2016-11-22 09:42:52 +03:00
t . ResponseContent = t . simpleMarshalJSON ( t . ResponseInfo )
2015-08-27 18:06:14 +03:00
}
}
2017-10-01 19:52:35 +03:00
// AfterLoad updates the webhook object upon setting a column
func ( t * HookTask ) AfterLoad ( ) {
t . DeliveredString = time . Unix ( 0 , t . Delivered ) . Format ( "2006-01-02 15:04:05 MST" )
if len ( t . RequestContent ) == 0 {
return
}
t . RequestInfo = & HookRequest { }
if err := json . Unmarshal ( [ ] byte ( t . RequestContent ) , t . RequestInfo ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Unmarshal RequestContent[%d]: %v" , t . ID , err )
2018-05-23 09:12:02 +03:00
}
if len ( t . ResponseContent ) > 0 {
t . ResponseInfo = & HookResponse { }
if err := json . Unmarshal ( [ ] byte ( t . ResponseContent ) , t . ResponseInfo ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Unmarshal ResponseContent[%d]: %v" , t . ID , err )
2018-05-23 09:12:02 +03:00
}
2015-08-27 18:06:14 +03:00
}
}
2016-11-22 09:42:52 +03:00
func ( t * HookTask ) simpleMarshalJSON ( v interface { } ) string {
2015-08-27 18:06:14 +03:00
p , err := json . Marshal ( v )
if err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Marshal [%d]: %v" , t . ID , err )
2015-08-27 18:06:14 +03:00
}
return string ( p )
}
// HookTasks returns a list of hook tasks by given conditions.
func HookTasks ( hookID int64 , page int ) ( [ ] * HookTask , error ) {
tasks := make ( [ ] * HookTask , 0 , setting . Webhook . PagingNum )
2016-11-10 18:16:32 +03:00
return tasks , x .
Limit ( setting . Webhook . PagingNum , ( page - 1 ) * setting . Webhook . PagingNum ) .
Where ( "hook_id=?" , hookID ) .
Desc ( "id" ) .
Find ( & tasks )
2014-06-08 12:45:34 +04:00
}
// CreateHookTask creates a new hook task,
// it handles conversion from Payload to PayloadContent.
func CreateHookTask ( t * HookTask ) error {
2017-09-03 11:20:24 +03:00
return createHookTask ( x , t )
}
func createHookTask ( e Engine , t * HookTask ) error {
2015-08-28 18:36:13 +03:00
data , err := t . Payloader . JSONPayload ( )
2014-06-08 12:45:34 +04:00
if err != nil {
return err
}
2016-02-21 02:13:12 +03:00
t . UUID = gouuid . NewV4 ( ) . String ( )
2014-06-08 12:45:34 +04:00
t . PayloadContent = string ( data )
2017-09-03 11:20:24 +03:00
_ , err = e . Insert ( t )
2014-06-08 12:45:34 +04:00
return err
}
// UpdateHookTask updates information of hook task.
func UpdateHookTask ( t * HookTask ) error {
2017-10-05 07:43:04 +03:00
_ , err := x . ID ( t . ID ) . AllCols ( ) . Update ( t )
2014-06-08 12:45:34 +04:00
return err
}
2019-11-02 01:51:22 +03:00
// FindUndeliveredHookTasks represents find the undelivered hook tasks
func FindUndeliveredHookTasks ( ) ( [ ] * HookTask , error ) {
2015-07-25 16:32:04 +03:00
tasks := make ( [ ] * HookTask , 0 , 10 )
2019-11-02 01:51:22 +03:00
if err := x . Where ( "is_delivered=?" , false ) . Find ( & tasks ) ; err != nil {
return nil , err
2014-09-13 02:58:24 +04:00
}
2019-11-02 01:51:22 +03:00
return tasks , nil
2014-06-08 12:45:34 +04:00
}
2015-07-25 16:32:04 +03:00
2019-11-02 01:51:22 +03:00
// FindRepoUndeliveredHookTasks represents find the undelivered hook tasks of one repository
func FindRepoUndeliveredHookTasks ( repoID int64 ) ( [ ] * HookTask , error ) {
tasks := make ( [ ] * HookTask , 0 , 5 )
if err := x . Where ( "repo_id=? AND is_delivered=?" , repoID , false ) . Find ( & tasks ) ; err != nil {
return nil , err
2019-05-21 10:20:17 +03:00
}
2019-11-02 01:51:22 +03:00
return tasks , nil
2015-07-25 16:32:04 +03:00
}