new create webhook event
This commit is contained in:
		
					parent
					
						
							
								a541ca16b6
							
						
					
				
			
			
				commit
				
					
						f509c59ac1
					
				
			
		
					 16 changed files with 449 additions and 306 deletions
				
			
		| 
						 | 
				
			
			@ -531,6 +531,12 @@ settings.content_type = Content Type
 | 
			
		|||
settings.secret = Secret
 | 
			
		||||
settings.event_desc = Upon which events should this webhook be triggered?
 | 
			
		||||
settings.event_push_only = Just the <code>push</code> event.
 | 
			
		||||
settings.event_send_everything = I need <strong>everything</strong>.
 | 
			
		||||
settings.event_choose = Let me choose what I need.
 | 
			
		||||
settings.event_create = Create
 | 
			
		||||
settings.event_create_desc = Branch, or tag created
 | 
			
		||||
settings.event_push = Push
 | 
			
		||||
settings.event_push_desc = Git push to a repository
 | 
			
		||||
settings.active = Active
 | 
			
		||||
settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
 | 
			
		||||
settings.add_hook_success = New webhook has been added.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										229
									
								
								models/action.go
									
										
									
									
									
								
							
							
						
						
									
										229
									
								
								models/action.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -16,6 +16,8 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/go-xorm/xorm"
 | 
			
		||||
 | 
			
		||||
	api "github.com/gogits/go-gogs-client"
 | 
			
		||||
 | 
			
		||||
	"github.com/gogits/gogs/modules/base"
 | 
			
		||||
	"github.com/gogits/gogs/modules/git"
 | 
			
		||||
	"github.com/gogits/gogs/modules/log"
 | 
			
		||||
| 
						 | 
				
			
			@ -290,20 +292,50 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// CommitRepoAction adds new action for committing repository.
 | 
			
		||||
func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
 | 
			
		||||
	repoID int64, repoUserName, repoName string, refFullName string, commit *base.PushCommits, oldCommitID string, newCommitID string) error {
 | 
			
		||||
func CommitRepoAction(
 | 
			
		||||
	userID, repoUserID int64,
 | 
			
		||||
	userName, actEmail string,
 | 
			
		||||
	repoID int64,
 | 
			
		||||
	repoUserName, repoName string,
 | 
			
		||||
	refFullName string,
 | 
			
		||||
	commit *base.PushCommits,
 | 
			
		||||
	oldCommitID string, newCommitID string) error {
 | 
			
		||||
 | 
			
		||||
	u, err := GetUserByID(userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetUserByID: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repo, err := GetRepositoryByName(repoUserID, repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetRepositoryByName: %v", err)
 | 
			
		||||
	} else if err = repo.GetOwner(); err != nil {
 | 
			
		||||
		return fmt.Errorf("GetOwner: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	isNewBranch := false
 | 
			
		||||
	opType := COMMIT_REPO
 | 
			
		||||
	// Check it's tag push or branch.
 | 
			
		||||
	if strings.HasPrefix(refFullName, "refs/tags/") {
 | 
			
		||||
		opType = PUSH_TAG
 | 
			
		||||
		commit = &base.PushCommits{}
 | 
			
		||||
	}
 | 
			
		||||
	} else {
 | 
			
		||||
		// if not the first commit, set the compareUrl
 | 
			
		||||
		if !strings.HasPrefix(oldCommitID, "0000000") {
 | 
			
		||||
			commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
 | 
			
		||||
		} else {
 | 
			
		||||
			isNewBranch = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
 | 
			
		||||
	// if not the first commit, set the compareUrl
 | 
			
		||||
	if !strings.HasPrefix(oldCommitID, "0000000") {
 | 
			
		||||
		commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
 | 
			
		||||
		// Change repository bare status and update last updated time.
 | 
			
		||||
		repo.IsBare = false
 | 
			
		||||
		if err = UpdateRepository(repo, false); err != nil {
 | 
			
		||||
			return fmt.Errorf("UpdateRepository: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
 | 
			
		||||
			log.Debug("updateIssuesCommit: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bs, err := json.Marshal(commit)
 | 
			
		||||
| 
						 | 
				
			
			@ -313,26 +345,6 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
 | 
			
		|||
 | 
			
		||||
	refName := git.RefEndName(refFullName)
 | 
			
		||||
 | 
			
		||||
	// Change repository bare status and update last updated time.
 | 
			
		||||
	repo, err := GetRepositoryByName(repoUserID, repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetRepositoryByName: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	repo.IsBare = false
 | 
			
		||||
	if err = UpdateRepository(repo, false); err != nil {
 | 
			
		||||
		return fmt.Errorf("UpdateRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u, err := GetUserByID(userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetUserByID: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Debug("updateIssuesCommit: ", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = NotifyWatchers(&Action{
 | 
			
		||||
		ActUserID:    u.Id,
 | 
			
		||||
		ActUserName:  userName,
 | 
			
		||||
| 
						 | 
				
			
			@ -345,32 +357,24 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
 | 
			
		|||
		RefName:      refName,
 | 
			
		||||
		IsPrivate:    repo.IsPrivate,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return errors.New("NotifyWatchers: " + err.Error())
 | 
			
		||||
		return fmt.Errorf("NotifyWatchers: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// New push event hook.
 | 
			
		||||
	if err := repo.GetOwner(); err != nil {
 | 
			
		||||
		return errors.New("GetOwner: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ws, err := GetActiveWebhooksByRepoId(repo.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("GetActiveWebhooksByRepoId: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check if repo belongs to org and append additional webhooks
 | 
			
		||||
	if repo.Owner.IsOrganization() {
 | 
			
		||||
		// get hooks for org
 | 
			
		||||
		orgws, err := GetActiveWebhooksByOrgId(repo.OwnerID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.New("GetActiveWebhooksByOrgId: " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		ws = append(ws, orgws...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ws) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
 | 
			
		||||
	payloadRepo := &api.PayloadRepo{
 | 
			
		||||
		ID:          repo.ID,
 | 
			
		||||
		Name:        repo.LowerName,
 | 
			
		||||
		URL:         repoLink,
 | 
			
		||||
		Description: repo.Description,
 | 
			
		||||
		Website:     repo.Website,
 | 
			
		||||
		Watchers:    repo.NumWatches,
 | 
			
		||||
		Owner: &api.PayloadAuthor{
 | 
			
		||||
			Name:     repo.Owner.DisplayName(),
 | 
			
		||||
			Email:    repo.Owner.Email,
 | 
			
		||||
			UserName: repo.Owner.Name,
 | 
			
		||||
		},
 | 
			
		||||
		Private: repo.IsPrivate,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pusher_email, pusher_name := "", ""
 | 
			
		||||
| 
						 | 
				
			
			@ -379,83 +383,66 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
 | 
			
		|||
		pusher_email = pusher.Email
 | 
			
		||||
		pusher_name = pusher.DisplayName()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commits := make([]*PayloadCommit, len(commit.Commits))
 | 
			
		||||
	for i, cmt := range commit.Commits {
 | 
			
		||||
		author_username := ""
 | 
			
		||||
		author, err := GetUserByEmail(cmt.AuthorEmail)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			author_username = author.Name
 | 
			
		||||
		}
 | 
			
		||||
		commits[i] = &PayloadCommit{
 | 
			
		||||
			Id:      cmt.Sha1,
 | 
			
		||||
			Message: cmt.Message,
 | 
			
		||||
			Url:     fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
 | 
			
		||||
			Author: &PayloadAuthor{
 | 
			
		||||
				Name:     cmt.AuthorName,
 | 
			
		||||
				Email:    cmt.AuthorEmail,
 | 
			
		||||
				UserName: author_username,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	p := &Payload{
 | 
			
		||||
		Ref:     refFullName,
 | 
			
		||||
		Commits: commits,
 | 
			
		||||
		Repo: &PayloadRepo{
 | 
			
		||||
			Id:          repo.ID,
 | 
			
		||||
			Name:        repo.LowerName,
 | 
			
		||||
			Url:         repoLink,
 | 
			
		||||
			Description: repo.Description,
 | 
			
		||||
			Website:     repo.Website,
 | 
			
		||||
			Watchers:    repo.NumWatches,
 | 
			
		||||
			Owner: &PayloadAuthor{
 | 
			
		||||
				Name:     repo.Owner.DisplayName(),
 | 
			
		||||
				Email:    repo.Owner.Email,
 | 
			
		||||
				UserName: repo.Owner.Name,
 | 
			
		||||
			},
 | 
			
		||||
			Private: repo.IsPrivate,
 | 
			
		||||
		},
 | 
			
		||||
		Pusher: &PayloadAuthor{
 | 
			
		||||
			Name:     pusher_name,
 | 
			
		||||
			Email:    pusher_email,
 | 
			
		||||
			UserName: userName,
 | 
			
		||||
		},
 | 
			
		||||
		Before:     oldCommitID,
 | 
			
		||||
		After:      newCommitID,
 | 
			
		||||
		CompareUrl: setting.AppUrl + commit.CompareUrl,
 | 
			
		||||
	payloadSender := &api.PayloadUser{
 | 
			
		||||
		UserName:  pusher.Name,
 | 
			
		||||
		ID:        pusher.Id,
 | 
			
		||||
		AvatarUrl: setting.AppUrl + pusher.RelAvatarLink(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, w := range ws {
 | 
			
		||||
		w.GetEvent()
 | 
			
		||||
		if !w.HasPushEvent() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var payload BasePayload
 | 
			
		||||
		switch w.HookTaskType {
 | 
			
		||||
		case SLACK:
 | 
			
		||||
			s, err := GetSlackPayload(p, w.Meta)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return errors.New("action.GetSlackPayload: " + err.Error())
 | 
			
		||||
	switch opType {
 | 
			
		||||
	case COMMIT_REPO: // Push
 | 
			
		||||
		commits := make([]*api.PayloadCommit, len(commit.Commits))
 | 
			
		||||
		for i, cmt := range commit.Commits {
 | 
			
		||||
			author_username := ""
 | 
			
		||||
			author, err := GetUserByEmail(cmt.AuthorEmail)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				author_username = author.Name
 | 
			
		||||
			}
 | 
			
		||||
			payload = s
 | 
			
		||||
		default:
 | 
			
		||||
			payload = p
 | 
			
		||||
			p.Secret = w.Secret
 | 
			
		||||
			commits[i] = &api.PayloadCommit{
 | 
			
		||||
				ID:      cmt.Sha1,
 | 
			
		||||
				Message: cmt.Message,
 | 
			
		||||
				URL:     fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
 | 
			
		||||
				Author: &api.PayloadAuthor{
 | 
			
		||||
					Name:     cmt.AuthorName,
 | 
			
		||||
					Email:    cmt.AuthorEmail,
 | 
			
		||||
					UserName: author_username,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		p := &api.PushPayload{
 | 
			
		||||
			Ref:        refFullName,
 | 
			
		||||
			Before:     oldCommitID,
 | 
			
		||||
			After:      newCommitID,
 | 
			
		||||
			CompareUrl: setting.AppUrl + commit.CompareUrl,
 | 
			
		||||
			Commits:    commits,
 | 
			
		||||
			Repo:       payloadRepo,
 | 
			
		||||
			Pusher: &api.PayloadAuthor{
 | 
			
		||||
				Name:     pusher_name,
 | 
			
		||||
				Email:    pusher_email,
 | 
			
		||||
				UserName: userName,
 | 
			
		||||
			},
 | 
			
		||||
			Sender: payloadSender,
 | 
			
		||||
		}
 | 
			
		||||
		if err = PrepareWebhooks(repo, HOOK_EVENT_PUSH, p); err != nil {
 | 
			
		||||
			return fmt.Errorf("PrepareWebhooks: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = CreateHookTask(&HookTask{
 | 
			
		||||
			RepoID:      repo.ID,
 | 
			
		||||
			HookID:      w.ID,
 | 
			
		||||
			Type:        w.HookTaskType,
 | 
			
		||||
			URL:         w.URL,
 | 
			
		||||
			BasePayload: payload,
 | 
			
		||||
			ContentType: w.ContentType,
 | 
			
		||||
			EventType:   HOOK_EVENT_PUSH,
 | 
			
		||||
			IsSSL:       w.IsSSL,
 | 
			
		||||
		}); err != nil {
 | 
			
		||||
			return fmt.Errorf("CreateHookTask: %v", err)
 | 
			
		||||
		if isNewBranch {
 | 
			
		||||
			return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
 | 
			
		||||
				Ref:     refName,
 | 
			
		||||
				RefType: "branch",
 | 
			
		||||
				Repo:    payloadRepo,
 | 
			
		||||
				Sender:  payloadSender,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case PUSH_TAG: // Create
 | 
			
		||||
		return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
 | 
			
		||||
			Ref:     refName,
 | 
			
		||||
			RefType: "tag",
 | 
			
		||||
			Repo:    payloadRepo,
 | 
			
		||||
			Sender:  payloadSender,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,9 +122,8 @@ func (u *User) HomeLink() string {
 | 
			
		|||
	return setting.AppSubUrl + "/" + u.Name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AvatarLink returns user gravatar link.
 | 
			
		||||
func (u *User) AvatarLink() string {
 | 
			
		||||
	defaultImgUrl := setting.AppSubUrl + "/img/avatar_default.jpg"
 | 
			
		||||
func (u *User) RelAvatarLink() string {
 | 
			
		||||
	defaultImgUrl := "/img/avatar_default.jpg"
 | 
			
		||||
	if u.Id == -1 {
 | 
			
		||||
		return defaultImgUrl
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +134,7 @@ func (u *User) AvatarLink() string {
 | 
			
		|||
		if !com.IsExist(imgPath) {
 | 
			
		||||
			return defaultImgUrl
 | 
			
		||||
		}
 | 
			
		||||
		return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
 | 
			
		||||
		return "/avatars/" + com.ToStr(u.Id)
 | 
			
		||||
	case setting.DisableGravatar, setting.OfflineMode:
 | 
			
		||||
		if !com.IsExist(imgPath) {
 | 
			
		||||
			img, err := avatar.RandomImage([]byte(u.Email))
 | 
			
		||||
| 
						 | 
				
			
			@ -161,13 +160,22 @@ func (u *User) AvatarLink() string {
 | 
			
		|||
			log.Info("New random avatar created: %d", u.Id)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
 | 
			
		||||
		return "/avatars/" + com.ToStr(u.Id)
 | 
			
		||||
	case setting.Service.EnableCacheAvatar:
 | 
			
		||||
		return setting.AppSubUrl + "/avatar/" + u.Avatar
 | 
			
		||||
		return "/avatar/" + u.Avatar
 | 
			
		||||
	}
 | 
			
		||||
	return setting.GravatarSource + u.Avatar
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AvatarLink returns user gravatar link.
 | 
			
		||||
func (u *User) AvatarLink() string {
 | 
			
		||||
	link := u.RelAvatarLink()
 | 
			
		||||
	if link[0] == '/' {
 | 
			
		||||
		return setting.AppSubUrl + link
 | 
			
		||||
	}
 | 
			
		||||
	return link
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewGitSig generates and returns the signature of given user.
 | 
			
		||||
func (u *User) NewGitSig() *git.Signature {
 | 
			
		||||
	return &git.Signature{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,8 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/go-xorm/xorm"
 | 
			
		||||
 | 
			
		||||
	api "github.com/gogits/go-gogs-client"
 | 
			
		||||
 | 
			
		||||
	"github.com/gogits/gogs/modules/httplib"
 | 
			
		||||
	"github.com/gogits/gogs/modules/log"
 | 
			
		||||
	"github.com/gogits/gogs/modules/setting"
 | 
			
		||||
| 
						 | 
				
			
			@ -54,9 +56,18 @@ func IsValidHookContentType(name string) bool {
 | 
			
		|||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HookEvents struct {
 | 
			
		||||
	Create bool `json:"create"`
 | 
			
		||||
	Push   bool `json:"push"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookEvent represents events that will delivery hook.
 | 
			
		||||
type HookEvent struct {
 | 
			
		||||
	PushOnly bool `json:"push_only"`
 | 
			
		||||
	PushOnly       bool `json:"push_only"`
 | 
			
		||||
	SendEverything bool `json:"send_everything"`
 | 
			
		||||
	ChooseEvents   bool `json:"choose_events"`
 | 
			
		||||
 | 
			
		||||
	HookEvents `json:"events"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HookStatus int
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +105,8 @@ func (w *Webhook) GetEvent() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *Webhook) GetSlackHook() *Slack {
 | 
			
		||||
	s := &Slack{}
 | 
			
		||||
func (w *Webhook) GetSlackHook() *SlackMeta {
 | 
			
		||||
	s := &SlackMeta{}
 | 
			
		||||
	if err := json.Unmarshal([]byte(w.Meta), s); err != nil {
 | 
			
		||||
		log.Error(4, "webhook.GetSlackHook(%d): %v", w.ID, err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -114,12 +125,16 @@ func (w *Webhook) UpdateEvent() error {
 | 
			
		|||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasCreateEvent returns true if hook enabled create event.
 | 
			
		||||
func (w *Webhook) HasCreateEvent() bool {
 | 
			
		||||
	return w.SendEverything ||
 | 
			
		||||
		(w.ChooseEvents && w.HookEvents.Create)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasPushEvent returns true if hook enabled push event.
 | 
			
		||||
func (w *Webhook) HasPushEvent() bool {
 | 
			
		||||
	if w.PushOnly {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
	return w.PushOnly || w.SendEverything ||
 | 
			
		||||
		(w.ChooseEvents && w.HookEvents.Push)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateWebhook creates a new web hook.
 | 
			
		||||
| 
						 | 
				
			
			@ -140,9 +155,9 @@ func GetWebhookByID(id int64) (*Webhook, error) {
 | 
			
		|||
	return w, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetActiveWebhooksByRepoId returns all active webhooks of repository.
 | 
			
		||||
func GetActiveWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
 | 
			
		||||
	err = x.Where("repo_id=?", repoId).And("is_active=?", true).Find(&ws)
 | 
			
		||||
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
 | 
			
		||||
func GetActiveWebhooksByRepoID(repoID int64) (ws []*Webhook, err error) {
 | 
			
		||||
	err = x.Where("repo_id=?", repoID).And("is_active=?", true).Find(&ws)
 | 
			
		||||
	return ws, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -181,9 +196,9 @@ func GetWebhooksByOrgId(orgID int64) (ws []*Webhook, err error) {
 | 
			
		|||
	return ws, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetActiveWebhooksByOrgId returns all active webhooks for an organization.
 | 
			
		||||
func GetActiveWebhooksByOrgId(orgId int64) (ws []*Webhook, err error) {
 | 
			
		||||
	err = x.Where("org_id=?", orgId).And("is_active=?", true).Find(&ws)
 | 
			
		||||
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
 | 
			
		||||
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
 | 
			
		||||
	err = x.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
 | 
			
		||||
	return ws, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,58 +245,10 @@ func IsValidHookTaskType(name string) bool {
 | 
			
		|||
type HookEventType string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	HOOK_EVENT_PUSH HookEventType = "push"
 | 
			
		||||
	HOOK_EVENT_CREATE HookEventType = "create"
 | 
			
		||||
	HOOK_EVENT_PUSH   HookEventType = "push"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FIXME: just use go-gogs-client structs maybe?
 | 
			
		||||
type PayloadAuthor struct {
 | 
			
		||||
	Name     string `json:"name"`
 | 
			
		||||
	Email    string `json:"email"`
 | 
			
		||||
	UserName string `json:"username"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PayloadCommit struct {
 | 
			
		||||
	Id      string         `json:"id"`
 | 
			
		||||
	Message string         `json:"message"`
 | 
			
		||||
	Url     string         `json:"url"`
 | 
			
		||||
	Author  *PayloadAuthor `json:"author"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PayloadRepo struct {
 | 
			
		||||
	Id          int64          `json:"id"`
 | 
			
		||||
	Name        string         `json:"name"`
 | 
			
		||||
	Url         string         `json:"url"`
 | 
			
		||||
	Description string         `json:"description"`
 | 
			
		||||
	Website     string         `json:"website"`
 | 
			
		||||
	Watchers    int            `json:"watchers"`
 | 
			
		||||
	Owner       *PayloadAuthor `json:"owner"`
 | 
			
		||||
	Private     bool           `json:"private"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BasePayload interface {
 | 
			
		||||
	GetJSONPayload() ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Payload represents a payload information of hook.
 | 
			
		||||
type Payload struct {
 | 
			
		||||
	Secret     string           `json:"secret"`
 | 
			
		||||
	Ref        string           `json:"ref"`
 | 
			
		||||
	Commits    []*PayloadCommit `json:"commits"`
 | 
			
		||||
	Repo       *PayloadRepo     `json:"repository"`
 | 
			
		||||
	Pusher     *PayloadAuthor   `json:"pusher"`
 | 
			
		||||
	Before     string           `json:"before"`
 | 
			
		||||
	After      string           `json:"after"`
 | 
			
		||||
	CompareUrl string           `json:"compare_url"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p Payload) GetJSONPayload() ([]byte, error) {
 | 
			
		||||
	data, err := json.MarshalIndent(p, "", "  ")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []byte{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookRequest represents hook task request information.
 | 
			
		||||
type HookRequest struct {
 | 
			
		||||
	Headers map[string]string `json:"headers"`
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +269,7 @@ type HookTask struct {
 | 
			
		|||
	UUID            string
 | 
			
		||||
	Type            HookTaskType
 | 
			
		||||
	URL             string
 | 
			
		||||
	BasePayload     `xorm:"-"`
 | 
			
		||||
	api.Payloader   `xorm:"-"`
 | 
			
		||||
	PayloadContent  string `xorm:"TEXT"`
 | 
			
		||||
	ContentType     HookContentType
 | 
			
		||||
	EventType       HookEventType
 | 
			
		||||
| 
						 | 
				
			
			@ -367,13 +334,13 @@ func (t *HookTask) MarshalJSON(v interface{}) string {
 | 
			
		|||
// 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)
 | 
			
		||||
	return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Desc("id").Find(&tasks)
 | 
			
		||||
	return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Where("hook_id=?", hookID).Desc("id").Find(&tasks)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateHookTask creates a new hook task,
 | 
			
		||||
// it handles conversion from Payload to PayloadContent.
 | 
			
		||||
func CreateHookTask(t *HookTask) error {
 | 
			
		||||
	data, err := t.BasePayload.GetJSONPayload()
 | 
			
		||||
	data, err := t.Payloader.JSONPayload()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -389,6 +356,71 @@ func UpdateHookTask(t *HookTask) error {
 | 
			
		|||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrepareWebhooks adds new webhooks to task queue for given payload.
 | 
			
		||||
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
 | 
			
		||||
	if err := repo.GetOwner(); err != nil {
 | 
			
		||||
		return fmt.Errorf("GetOwner: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ws, err := GetActiveWebhooksByRepoID(repo.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check if repo belongs to org and append additional webhooks
 | 
			
		||||
	if repo.Owner.IsOrganization() {
 | 
			
		||||
		// get hooks for org
 | 
			
		||||
		orgws, err := GetActiveWebhooksByOrgID(repo.OwnerID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		ws = append(ws, orgws...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ws) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, w := range ws {
 | 
			
		||||
		w.GetEvent()
 | 
			
		||||
 | 
			
		||||
		switch event {
 | 
			
		||||
		case HOOK_EVENT_CREATE:
 | 
			
		||||
			if !w.HasCreateEvent() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		case HOOK_EVENT_PUSH:
 | 
			
		||||
			if !w.HasPushEvent() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch w.HookTaskType {
 | 
			
		||||
		case SLACK:
 | 
			
		||||
			p, err = GetSlackPayload(p, event, w.Meta)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return fmt.Errorf("GetSlackPayload: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			p.SetSecret(w.Secret)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = CreateHookTask(&HookTask{
 | 
			
		||||
			RepoID:      repo.ID,
 | 
			
		||||
			HookID:      w.ID,
 | 
			
		||||
			Type:        w.HookTaskType,
 | 
			
		||||
			URL:         w.URL,
 | 
			
		||||
			Payloader:   p,
 | 
			
		||||
			ContentType: w.ContentType,
 | 
			
		||||
			EventType:   HOOK_EVENT_PUSH,
 | 
			
		||||
			IsSSL:       w.IsSSL,
 | 
			
		||||
		}); err != nil {
 | 
			
		||||
			return fmt.Errorf("CreateHookTask: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type hookQueue struct {
 | 
			
		||||
	// Make sure one repository only occur once in the queue.
 | 
			
		||||
	lock    sync.Mutex
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,13 +9,18 @@ import (
 | 
			
		|||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	api "github.com/gogits/go-gogs-client"
 | 
			
		||||
 | 
			
		||||
	"github.com/gogits/gogs/modules/git"
 | 
			
		||||
	"github.com/gogits/gogs/modules/setting"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	SLACK_COLOR string = "#dd4b39"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Slack struct {
 | 
			
		||||
type SlackMeta struct {
 | 
			
		||||
	Channel string `json:"channel"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +39,9 @@ type SlackAttachment struct {
 | 
			
		|||
	Text  string `json:"text"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p SlackPayload) GetJSONPayload() ([]byte, error) {
 | 
			
		||||
func (p *SlackPayload) SetSecret(_ string) {}
 | 
			
		||||
 | 
			
		||||
func (p *SlackPayload) JSONPayload() ([]byte, error) {
 | 
			
		||||
	data, err := json.Marshal(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []byte{}, err
 | 
			
		||||
| 
						 | 
				
			
			@ -42,63 +49,6 @@ func (p SlackPayload) GetJSONPayload() ([]byte, error) {
 | 
			
		|||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSlackPayload(p *Payload, meta string) (*SlackPayload, error) {
 | 
			
		||||
	slack := &Slack{}
 | 
			
		||||
	slackPayload := &SlackPayload{}
 | 
			
		||||
	if err := json.Unmarshal([]byte(meta), &slack); err != nil {
 | 
			
		||||
		return slackPayload, errors.New("GetSlackPayload meta json:" + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: handle different payload types: push, new branch, delete branch etc.
 | 
			
		||||
	// when they are added to gogs. Only handles push now
 | 
			
		||||
	return getSlackPushPayload(p, slack)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getSlackPushPayload(p *Payload, slack *Slack) (*SlackPayload, error) {
 | 
			
		||||
	// n new commits
 | 
			
		||||
	refSplit := strings.Split(p.Ref, "/")
 | 
			
		||||
	branchName := refSplit[len(refSplit)-1]
 | 
			
		||||
	var commitString string
 | 
			
		||||
 | 
			
		||||
	if len(p.Commits) == 1 {
 | 
			
		||||
		commitString = "1 new commit"
 | 
			
		||||
		if p.CompareUrl != "" {
 | 
			
		||||
			commitString = SlackLinkFormatter(p.CompareUrl, commitString)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		commitString = fmt.Sprintf("%d new commits", len(p.Commits))
 | 
			
		||||
		if p.CompareUrl != "" {
 | 
			
		||||
			commitString = SlackLinkFormatter(p.CompareUrl, commitString)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repoLink := SlackLinkFormatter(p.Repo.Url, p.Repo.Name)
 | 
			
		||||
	branchLink := SlackLinkFormatter(p.Repo.Url+"/src/"+branchName, branchName)
 | 
			
		||||
	text := fmt.Sprintf("[%s:%s] %s pushed by %s", repoLink, branchLink, commitString, p.Pusher.Name)
 | 
			
		||||
	var attachmentText string
 | 
			
		||||
 | 
			
		||||
	// for each commit, generate attachment text
 | 
			
		||||
	for i, commit := range p.Commits {
 | 
			
		||||
		attachmentText += fmt.Sprintf("%s: %s - %s", SlackLinkFormatter(commit.Url, commit.Id[:7]), SlackTextFormatter(commit.Message), SlackTextFormatter(commit.Author.Name))
 | 
			
		||||
		// add linebreak to each commit but the last
 | 
			
		||||
		if i < len(p.Commits)-1 {
 | 
			
		||||
			attachmentText += "\n"
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	slackAttachments := []SlackAttachment{{Color: SLACK_COLOR, Text: attachmentText}}
 | 
			
		||||
 | 
			
		||||
	return &SlackPayload{
 | 
			
		||||
		Channel:     slack.Channel,
 | 
			
		||||
		Text:        text,
 | 
			
		||||
		Username:    "gogs",
 | 
			
		||||
		IconUrl:     "https://raw.githubusercontent.com/gogits/gogs/master/public/img/favicon.png",
 | 
			
		||||
		UnfurlLinks: 0,
 | 
			
		||||
		LinkNames:   0,
 | 
			
		||||
		Attachments: slackAttachments,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// see: https://api.slack.com/docs/formatting
 | 
			
		||||
func SlackTextFormatter(s string) string {
 | 
			
		||||
	// take only first line of commit
 | 
			
		||||
| 
						 | 
				
			
			@ -113,3 +63,81 @@ func SlackTextFormatter(s string) string {
 | 
			
		|||
func SlackLinkFormatter(url string, text string) string {
 | 
			
		||||
	return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) {
 | 
			
		||||
	// created tag/branch
 | 
			
		||||
	refName := git.RefEndName(p.Ref)
 | 
			
		||||
 | 
			
		||||
	repoLink := SlackLinkFormatter(p.Repo.URL, p.Repo.Name)
 | 
			
		||||
	refLink := SlackLinkFormatter(p.Repo.URL+"/src/"+refName, refName)
 | 
			
		||||
	text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName)
 | 
			
		||||
 | 
			
		||||
	return &SlackPayload{
 | 
			
		||||
		Channel:  slack.Channel,
 | 
			
		||||
		Text:     text,
 | 
			
		||||
		Username: setting.AppName,
 | 
			
		||||
		IconUrl:  setting.AppUrl + "/img/favicon.png",
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, error) {
 | 
			
		||||
	// n new commits
 | 
			
		||||
	var (
 | 
			
		||||
		branchName   = git.RefEndName(p.Ref)
 | 
			
		||||
		commitString string
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if len(p.Commits) == 1 {
 | 
			
		||||
		commitString = "1 new commit"
 | 
			
		||||
		if len(p.CompareUrl) > 0 {
 | 
			
		||||
			commitString = SlackLinkFormatter(p.CompareUrl, commitString)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		commitString = fmt.Sprintf("%d new commits", len(p.Commits))
 | 
			
		||||
		if p.CompareUrl != "" {
 | 
			
		||||
			commitString = SlackLinkFormatter(p.CompareUrl, commitString)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repoLink := SlackLinkFormatter(p.Repo.URL, p.Repo.Name)
 | 
			
		||||
	branchLink := SlackLinkFormatter(p.Repo.URL+"/src/"+branchName, branchName)
 | 
			
		||||
	text := fmt.Sprintf("[%s:%s] %s pushed by %s", repoLink, branchLink, commitString, p.Pusher.Name)
 | 
			
		||||
 | 
			
		||||
	var attachmentText string
 | 
			
		||||
	// for each commit, generate attachment text
 | 
			
		||||
	for i, commit := range p.Commits {
 | 
			
		||||
		attachmentText += fmt.Sprintf("%s: %s - %s", SlackLinkFormatter(commit.URL, commit.ID[:7]), SlackTextFormatter(commit.Message), SlackTextFormatter(commit.Author.Name))
 | 
			
		||||
		// add linebreak to each commit but the last
 | 
			
		||||
		if i < len(p.Commits)-1 {
 | 
			
		||||
			attachmentText += "\n"
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	slackAttachments := []SlackAttachment{{Color: SLACK_COLOR, Text: attachmentText}}
 | 
			
		||||
 | 
			
		||||
	return &SlackPayload{
 | 
			
		||||
		Channel:     slack.Channel,
 | 
			
		||||
		Text:        text,
 | 
			
		||||
		Username:    setting.AppName,
 | 
			
		||||
		IconUrl:     setting.AppUrl + "/img/favicon.png",
 | 
			
		||||
		Attachments: slackAttachments,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
 | 
			
		||||
	s := new(SlackPayload)
 | 
			
		||||
 | 
			
		||||
	slack := &SlackMeta{}
 | 
			
		||||
	if err := json.Unmarshal([]byte(meta), &slack); err != nil {
 | 
			
		||||
		return s, errors.New("GetSlackPayload meta json:" + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch event {
 | 
			
		||||
	case HOOK_EVENT_CREATE:
 | 
			
		||||
		return getSlackCreatePayload(p.(*api.CreatePayload), slack)
 | 
			
		||||
	case HOOK_EVENT_PUSH:
 | 
			
		||||
		return getSlackPushPayload(p.(*api.PushPayload), slack)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,8 +67,22 @@ func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
 | 
			
		|||
//        \/       \/    \/     \/     \/            \/
 | 
			
		||||
 | 
			
		||||
type WebhookForm struct {
 | 
			
		||||
	PushOnly bool
 | 
			
		||||
	Active   bool
 | 
			
		||||
	Events string
 | 
			
		||||
	Create bool
 | 
			
		||||
	Push   bool
 | 
			
		||||
	Active bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f WebhookForm) PushOnly() bool {
 | 
			
		||||
	return f.Events == "push_only"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f WebhookForm) SendEverything() bool {
 | 
			
		||||
	return f.Events == "send_everything"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f WebhookForm) ChooseEvents() bool {
 | 
			
		||||
	return f.Events == "choose_events"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NewWebhookForm struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								public/css/gogs.min.css
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/css/gogs.min.css
									
										
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -367,6 +367,23 @@ function initRepository() {
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function initWebhook() {
 | 
			
		||||
    if ($('.new.webhook').length == 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $('.events.checkbox input').change(function () {
 | 
			
		||||
        if ($(this).is(':checked')) {
 | 
			
		||||
            $('.events.fields').show();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    $('.non-events.checkbox input').change(function () {
 | 
			
		||||
        if ($(this).is(':checked')) {
 | 
			
		||||
            $('.events.fields').hide();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
    csrf = $('meta[name=_csrf]').attr("content");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -473,4 +490,5 @@ $(document).ready(function () {
 | 
			
		|||
    initCommentForm();
 | 
			
		||||
    initInstall();
 | 
			
		||||
    initRepository();
 | 
			
		||||
    initWebhook();
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -76,4 +76,12 @@
 | 
			
		|||
			margin-left: 25px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.new.webhook {
 | 
			
		||||
	.events.fields {
 | 
			
		||||
		.column {
 | 
			
		||||
			padding-left: 40px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ func CreateRepoHook(ctx *middleware.Context, form api.CreateHookOption) {
 | 
			
		|||
			ctx.JSON(422, &base.ApiJsonErr{"missing config option: channel", base.DOC_URL})
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		meta, err := json.Marshal(&models.Slack{
 | 
			
		||||
		meta, err := json.Marshal(&models.SlackMeta{
 | 
			
		||||
			Channel: channel,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ func EditRepoHook(ctx *middleware.Context, form api.EditHookOption) {
 | 
			
		|||
 | 
			
		||||
		if w.HookTaskType == models.SLACK {
 | 
			
		||||
			if channel, ok := form.Config["channel"]; ok {
 | 
			
		||||
				meta, err := json.Marshal(&models.Slack{
 | 
			
		||||
				meta, err := json.Marshal(&models.SlackMeta{
 | 
			
		||||
					Channel: channel,
 | 
			
		||||
				})
 | 
			
		||||
				if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -320,6 +320,18 @@ func WebhooksNew(ctx *middleware.Context) {
 | 
			
		|||
	ctx.HTML(200, orCtx.NewTemplate)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
 | 
			
		||||
	return &models.HookEvent{
 | 
			
		||||
		PushOnly:       form.PushOnly(),
 | 
			
		||||
		SendEverything: form.SendEverything(),
 | 
			
		||||
		ChooseEvents:   form.ChooseEvents(),
 | 
			
		||||
		HookEvents: models.HookEvents{
 | 
			
		||||
			Create: form.Create,
 | 
			
		||||
			Push:   form.Push,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
 | 
			
		||||
	ctx.Data["PageIsSettingsHooks"] = true
 | 
			
		||||
| 
						 | 
				
			
			@ -345,13 +357,11 @@ func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	w := &models.Webhook{
 | 
			
		||||
		RepoID:      orCtx.RepoID,
 | 
			
		||||
		URL:         form.PayloadURL,
 | 
			
		||||
		ContentType: contentType,
 | 
			
		||||
		Secret:      form.Secret,
 | 
			
		||||
		HookEvent: &models.HookEvent{
 | 
			
		||||
			PushOnly: form.PushOnly,
 | 
			
		||||
		},
 | 
			
		||||
		RepoID:       orCtx.RepoID,
 | 
			
		||||
		URL:          form.PayloadURL,
 | 
			
		||||
		ContentType:  contentType,
 | 
			
		||||
		Secret:       form.Secret,
 | 
			
		||||
		HookEvent:    ParseHookEvent(form.WebhookForm),
 | 
			
		||||
		IsActive:     form.Active,
 | 
			
		||||
		HookTaskType: models.GOGS,
 | 
			
		||||
		OrgID:        orCtx.OrgID,
 | 
			
		||||
| 
						 | 
				
			
			@ -385,7 +395,7 @@ func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	meta, err := json.Marshal(&models.Slack{
 | 
			
		||||
	meta, err := json.Marshal(&models.SlackMeta{
 | 
			
		||||
		Channel: form.Channel,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -394,12 +404,10 @@ func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	w := &models.Webhook{
 | 
			
		||||
		RepoID:      orCtx.RepoID,
 | 
			
		||||
		URL:         form.PayloadURL,
 | 
			
		||||
		ContentType: models.JSON,
 | 
			
		||||
		HookEvent: &models.HookEvent{
 | 
			
		||||
			PushOnly: form.PushOnly,
 | 
			
		||||
		},
 | 
			
		||||
		RepoID:       orCtx.RepoID,
 | 
			
		||||
		URL:          form.PayloadURL,
 | 
			
		||||
		ContentType:  models.JSON,
 | 
			
		||||
		HookEvent:    ParseHookEvent(form.WebhookForm),
 | 
			
		||||
		IsActive:     form.Active,
 | 
			
		||||
		HookTaskType: models.SLACK,
 | 
			
		||||
		Meta:         string(meta),
 | 
			
		||||
| 
						 | 
				
			
			@ -491,9 +499,7 @@ func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) {
 | 
			
		|||
	w.URL = form.PayloadURL
 | 
			
		||||
	w.ContentType = contentType
 | 
			
		||||
	w.Secret = form.Secret
 | 
			
		||||
	w.HookEvent = &models.HookEvent{
 | 
			
		||||
		PushOnly: form.PushOnly,
 | 
			
		||||
	}
 | 
			
		||||
	w.HookEvent = ParseHookEvent(form.WebhookForm)
 | 
			
		||||
	w.IsActive = form.Active
 | 
			
		||||
	if err := w.UpdateEvent(); err != nil {
 | 
			
		||||
		ctx.Handle(500, "UpdateEvent", err)
 | 
			
		||||
| 
						 | 
				
			
			@ -523,7 +529,7 @@ func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	meta, err := json.Marshal(&models.Slack{
 | 
			
		||||
	meta, err := json.Marshal(&models.SlackMeta{
 | 
			
		||||
		Channel: form.Channel,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -533,9 +539,7 @@ func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
 | 
			
		|||
 | 
			
		||||
	w.URL = form.PayloadURL
 | 
			
		||||
	w.Meta = string(meta)
 | 
			
		||||
	w.HookEvent = &models.HookEvent{
 | 
			
		||||
		PushOnly: form.PushOnly,
 | 
			
		||||
	}
 | 
			
		||||
	w.HookEvent = ParseHookEvent(form.WebhookForm)
 | 
			
		||||
	w.IsActive = form.Active
 | 
			
		||||
	if err := w.UpdateEvent(); err != nil {
 | 
			
		||||
		ctx.Handle(500, "UpdateEvent", err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,4 +26,22 @@
 | 
			
		|||
		</div>
 | 
			
		||||
	</footer>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
	<!-- Third-party libraries -->
 | 
			
		||||
	{{if .RequireHighlightJS}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/highlight-8.7/default.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/highlight-8.7.pack.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireMinicolors}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.minicolors-2.1.12.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/jquery.minicolors-2.1.12.min.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireDatetimepicker}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.datetimepicker-2.4.5.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/jquery.datetimepicker-2.4.5.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireDropzone}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/dropzone-4.0.1.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/dropzone-4.0.1.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -25,24 +25,6 @@
 | 
			
		|||
	<script src="{{AppSubUrl}}/js/semantic-2.0.8.min.js"></script>
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/gogs.js?v={{AppVer}}"></script>
 | 
			
		||||
 | 
			
		||||
	<!-- Third-party libraries -->
 | 
			
		||||
	{{if .RequireHighlightJS}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/highlight-8.7/default.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/highlight-8.7.pack.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireMinicolors}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.minicolors-2.1.12.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/jquery.minicolors-2.1.12.min.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireDatetimepicker}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.datetimepicker-2.4.5.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/jquery.datetimepicker-2.4.5.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	{{if .RequireDropzone}}
 | 
			
		||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/dropzone-4.0.1.css">
 | 
			
		||||
	<script src="{{AppSubUrl}}/js/libs/dropzone-4.0.1.js"></script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
 | 
			
		||||
	<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@
 | 
			
		|||
					  	{{if .IsSucceed}}
 | 
			
		||||
					  	<span class="ui green label">{{.ResponseInfo.Status}}</span>
 | 
			
		||||
					  	{{else}}
 | 
			
		||||
					  	<span class="ui red label">500</span>
 | 
			
		||||
					  	<span class="ui red label">{{.ResponseInfo.Status}}</span>
 | 
			
		||||
					  	{{end}}
 | 
			
		||||
				  	{{else}}
 | 
			
		||||
				  		<span class="ui label">N/A</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,52 @@
 | 
			
		|||
<div class="field">
 | 
			
		||||
  <h4>{{.i18n.Tr "repo.settings.event_desc"}}</h4>
 | 
			
		||||
	<div class="grouped fields">
 | 
			
		||||
		<div class="field">
 | 
			
		||||
		  <div class="ui radio checkbox checked">
 | 
			
		||||
		    <input class="hidden" name="push_only" type="radio" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}>
 | 
			
		||||
		    <label>{{.i18n.Tr "repo.settings.event_push_only" | Str2html}}</label>
 | 
			
		||||
		  </div>
 | 
			
		||||
		</div>
 | 
			
		||||
	<div class="grouped event type fields">
 | 
			
		||||
    <div class="field">
 | 
			
		||||
      <div class="ui radio non-events checkbox">
 | 
			
		||||
        <input class="hidden" name="events" type="radio" value="push_only" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}>
 | 
			
		||||
        <label>{{.i18n.Tr "repo.settings.event_push_only" | Str2html}}</label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="field">
 | 
			
		||||
      <div class="ui radio non-events checkbox">
 | 
			
		||||
        <input class="hidden" name="events" type="radio" value="send_everything" {{if .Webhook.SendEverything}}checked{{end}}>
 | 
			
		||||
        <label>{{.i18n.Tr "repo.settings.event_send_everything" | Str2html}}</label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="field">
 | 
			
		||||
      <div class="ui radio events checkbox">
 | 
			
		||||
        <input class="hidden" name="events" type="radio" value="choose_events" {{if .Webhook.ChooseEvents}}checked{{end}}>
 | 
			
		||||
        <label>{{.i18n.Tr "repo.settings.event_choose" | Str2html}}</label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
  <div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}>
 | 
			
		||||
    <!-- Create -->
 | 
			
		||||
    <div class="seven wide column">
 | 
			
		||||
      <div class="field">
 | 
			
		||||
        <div class="ui checkbox">
 | 
			
		||||
          <input class="hidden" name="create" type="checkbox" tabindex="0" {{if .Webhook.Create}}checked{{end}}>
 | 
			
		||||
          <label>{{.i18n.Tr "repo.settings.event_create"}}</label>
 | 
			
		||||
          <span class="help">{{.i18n.Tr "repo.settings.event_create_desc"}}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <!-- Push -->
 | 
			
		||||
    <div class="seven wide column">
 | 
			
		||||
      <div class="field">
 | 
			
		||||
        <div class="ui checkbox">
 | 
			
		||||
          <input class="hidden" name="push" type="checkbox" tabindex="0" {{if .Webhook.Push}}checked{{end}}>
 | 
			
		||||
          <label>{{.i18n.Tr "repo.settings.event_push"}}</label>
 | 
			
		||||
            <span class="help">{{.i18n.Tr "repo.settings.event_push_desc"}}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="ui divider"></div>
 | 
			
		||||
 | 
			
		||||
<div class="inline field">
 | 
			
		||||
  <div class="ui checkbox">
 | 
			
		||||
    <input class="hidden" name="active" type="checkbox" tabindex="0" {{if or .PageIsSettingsHooksNew .Webhook.IsActive}}checked{{end}}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue