summaryrefslogtreecommitdiffstats
path: root/routers/repo/webhook.go
diff options
context:
space:
mode:
authorUnknwon <u@gogs.io>2015-12-05 13:24:13 -0500
committerUnknwon <u@gogs.io>2015-12-05 13:24:13 -0500
commit404867f206f97ec4ea2e6032fea47bc0499d3497 (patch)
treeb37be9387d2a00cd2447e65a1367bb292c6c0a09 /routers/repo/webhook.go
parentf0ee33267c453cc7f77a87a2b4b784febbb604dd (diff)
downloadgitea-404867f206f97ec4ea2e6032fea47bc0499d3497.tar.gz
gitea-404867f206f97ec4ea2e6032fea47bc0499d3497.zip
fix #2105 and fix #1857
Diffstat (limited to 'routers/repo/webhook.go')
-rw-r--r--routers/repo/webhook.go385
1 files changed, 385 insertions, 0 deletions
diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go
new file mode 100644
index 0000000000..b93d6fc284
--- /dev/null
+++ b/routers/repo/webhook.go
@@ -0,0 +1,385 @@
+// Copyright 2015 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package repo
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/Unknwon/com"
+
+ api "github.com/gogits/go-gogs-client"
+
+ "github.com/gogits/gogs/models"
+ "github.com/gogits/gogs/modules/auth"
+ "github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/middleware"
+ "github.com/gogits/gogs/modules/setting"
+)
+
+const (
+ HOOKS base.TplName = "repo/settings/hooks"
+ HOOK_NEW base.TplName = "repo/settings/hook_new"
+ ORG_HOOK_NEW base.TplName = "org/settings/hook_new"
+)
+
+func Webhooks(ctx *middleware.Context) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings.hooks")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["BaseLink"] = ctx.Repo.RepoLink
+ ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://github.com/gogits/go-gogs-client/wiki/Repositories-Webhooks")
+
+ ws, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID)
+ if err != nil {
+ ctx.Handle(500, "GetWebhooksByRepoID", err)
+ return
+ }
+ ctx.Data["Webhooks"] = ws
+
+ ctx.HTML(200, HOOKS)
+}
+
+type OrgRepoCtx struct {
+ OrgID int64
+ RepoID int64
+ Link string
+ NewTemplate base.TplName
+}
+
+// getOrgRepoCtx determines whether this is a repo context or organization context.
+func getOrgRepoCtx(ctx *middleware.Context) (*OrgRepoCtx, error) {
+ if len(ctx.Repo.RepoLink) > 0 {
+ return &OrgRepoCtx{
+ RepoID: ctx.Repo.Repository.ID,
+ Link: ctx.Repo.RepoLink,
+ NewTemplate: HOOK_NEW,
+ }, nil
+ }
+
+ if len(ctx.Org.OrgLink) > 0 {
+ return &OrgRepoCtx{
+ OrgID: ctx.Org.Organization.Id,
+ Link: ctx.Org.OrgLink,
+ NewTemplate: ORG_HOOK_NEW,
+ }, nil
+ }
+
+ return nil, errors.New("Unable to set OrgRepo context")
+}
+
+func checkHookType(ctx *middleware.Context) string {
+ hookType := strings.ToLower(ctx.Params(":type"))
+ if !com.IsSliceContainsStr(setting.Webhook.Types, hookType) {
+ ctx.Handle(404, "checkHookType", nil)
+ return ""
+ }
+ return hookType
+}
+
+func WebhooksNew(ctx *middleware.Context) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["PageIsSettingsHooksNew"] = true
+ ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
+
+ orCtx, err := getOrgRepoCtx(ctx)
+ if err != nil {
+ ctx.Handle(500, "getOrgRepoCtx", err)
+ return
+ }
+
+ ctx.Data["HookType"] = checkHookType(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["BaseLink"] = orCtx.Link
+
+ 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
+ ctx.Data["PageIsSettingsHooksNew"] = true
+ ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
+ ctx.Data["HookType"] = "gogs"
+
+ orCtx, err := getOrgRepoCtx(ctx)
+ if err != nil {
+ ctx.Handle(500, "getOrgRepoCtx", err)
+ return
+ }
+ ctx.Data["BaseLink"] = orCtx.Link
+
+ if ctx.HasError() {
+ ctx.HTML(200, orCtx.NewTemplate)
+ return
+ }
+
+ contentType := models.JSON
+ if models.HookContentType(form.ContentType) == models.FORM {
+ contentType = models.FORM
+ }
+
+ w := &models.Webhook{
+ RepoID: orCtx.RepoID,
+ URL: form.PayloadURL,
+ ContentType: contentType,
+ Secret: form.Secret,
+ HookEvent: ParseHookEvent(form.WebhookForm),
+ IsActive: form.Active,
+ HookTaskType: models.GOGS,
+ OrgID: orCtx.OrgID,
+ }
+ if err := w.UpdateEvent(); err != nil {
+ ctx.Handle(500, "UpdateEvent", err)
+ return
+ } else if err := models.CreateWebhook(w); err != nil {
+ ctx.Handle(500, "CreateWebhook", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success"))
+ ctx.Redirect(orCtx.Link + "/settings/hooks")
+}
+
+func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["PageIsSettingsHooksNew"] = true
+ ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
+
+ orCtx, err := getOrgRepoCtx(ctx)
+ if err != nil {
+ ctx.Handle(500, "getOrgRepoCtx", err)
+ return
+ }
+
+ if ctx.HasError() {
+ ctx.HTML(200, orCtx.NewTemplate)
+ return
+ }
+
+ meta, err := json.Marshal(&models.SlackMeta{
+ Channel: form.Channel,
+ Username: form.Username,
+ IconURL: form.IconURL,
+ Color: form.Color,
+ })
+ if err != nil {
+ ctx.Handle(500, "Marshal", err)
+ return
+ }
+
+ w := &models.Webhook{
+ RepoID: orCtx.RepoID,
+ URL: form.PayloadURL,
+ ContentType: models.JSON,
+ HookEvent: ParseHookEvent(form.WebhookForm),
+ IsActive: form.Active,
+ HookTaskType: models.SLACK,
+ Meta: string(meta),
+ OrgID: orCtx.OrgID,
+ }
+ if err := w.UpdateEvent(); err != nil {
+ ctx.Handle(500, "UpdateEvent", err)
+ return
+ } else if err := models.CreateWebhook(w); err != nil {
+ ctx.Handle(500, "CreateWebhook", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success"))
+ ctx.Redirect(orCtx.Link + "/settings/hooks")
+}
+
+func checkWebhook(ctx *middleware.Context) (*OrgRepoCtx, *models.Webhook) {
+ ctx.Data["RequireHighlightJS"] = true
+
+ orCtx, err := getOrgRepoCtx(ctx)
+ if err != nil {
+ ctx.Handle(500, "getOrgRepoCtx", err)
+ return nil, nil
+ }
+ ctx.Data["BaseLink"] = orCtx.Link
+
+ w, err := models.GetWebhookByID(ctx.ParamsInt64(":id"))
+ if err != nil {
+ if models.IsErrWebhookNotExist(err) {
+ ctx.Handle(404, "GetWebhookByID", nil)
+ } else {
+ ctx.Handle(500, "GetWebhookByID", err)
+ }
+ return nil, nil
+ }
+
+ switch w.HookTaskType {
+ case models.SLACK:
+ ctx.Data["SlackHook"] = w.GetSlackHook()
+ ctx.Data["HookType"] = "slack"
+ default:
+ ctx.Data["HookType"] = "gogs"
+ }
+
+ ctx.Data["History"], err = w.History(1)
+ if err != nil {
+ ctx.Handle(500, "History", err)
+ }
+ return orCtx, w
+}
+
+func WebHooksEdit(ctx *middleware.Context) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["PageIsSettingsHooksEdit"] = true
+
+ orCtx, w := checkWebhook(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["Webhook"] = w
+
+ ctx.HTML(200, orCtx.NewTemplate)
+}
+
+func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["PageIsSettingsHooksEdit"] = true
+
+ orCtx, w := checkWebhook(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["Webhook"] = w
+
+ if ctx.HasError() {
+ ctx.HTML(200, orCtx.NewTemplate)
+ return
+ }
+
+ contentType := models.JSON
+ if models.HookContentType(form.ContentType) == models.FORM {
+ contentType = models.FORM
+ }
+
+ w.URL = form.PayloadURL
+ w.ContentType = contentType
+ w.Secret = form.Secret
+ w.HookEvent = ParseHookEvent(form.WebhookForm)
+ w.IsActive = form.Active
+ if err := w.UpdateEvent(); err != nil {
+ ctx.Handle(500, "UpdateEvent", err)
+ return
+ } else if err := models.UpdateWebhook(w); err != nil {
+ ctx.Handle(500, "WebHooksEditPost", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success"))
+ ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
+}
+
+func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
+ ctx.Data["Title"] = ctx.Tr("repo.settings")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["PageIsSettingsHooksEdit"] = true
+
+ orCtx, w := checkWebhook(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["Webhook"] = w
+
+ if ctx.HasError() {
+ ctx.HTML(200, orCtx.NewTemplate)
+ return
+ }
+
+ meta, err := json.Marshal(&models.SlackMeta{
+ Channel: form.Channel,
+ Username: form.Username,
+ IconURL: form.IconURL,
+ Color: form.Color,
+ })
+ if err != nil {
+ ctx.Handle(500, "Marshal", err)
+ return
+ }
+
+ w.URL = form.PayloadURL
+ w.Meta = string(meta)
+ w.HookEvent = ParseHookEvent(form.WebhookForm)
+ w.IsActive = form.Active
+ if err := w.UpdateEvent(); err != nil {
+ ctx.Handle(500, "UpdateEvent", err)
+ return
+ } else if err := models.UpdateWebhook(w); err != nil {
+ ctx.Handle(500, "UpdateWebhook", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success"))
+ ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
+}
+
+func TestWebhook(ctx *middleware.Context) {
+ p := &api.PushPayload{
+ Ref: ctx.Repo.Repository.DefaultBranch,
+ Before: ctx.Repo.CommitID,
+ After: ctx.Repo.CommitID,
+ Commits: []*api.PayloadCommit{
+ {
+ ID: ctx.Repo.CommitID,
+ Message: ctx.Repo.Commit.Message(),
+ URL: ctx.Repo.RepoLink + "/commit/" + ctx.Repo.CommitID,
+ Author: &api.PayloadAuthor{
+ Name: ctx.Repo.Commit.Author.Name,
+ Email: ctx.Repo.Commit.Author.Email,
+ },
+ },
+ },
+ Repo: ctx.Repo.Repository.ComposePayload(),
+ Sender: &api.PayloadUser{
+ UserName: ctx.User.Name,
+ ID: ctx.User.Id,
+ AvatarUrl: setting.AppUrl + ctx.User.RelAvatarLink(),
+ },
+ }
+ if err := models.PrepareWebhooks(ctx.Repo.Repository, models.HOOK_EVENT_PUSH, p); err != nil {
+ ctx.Flash.Error("PrepareWebhooks: " + err.Error())
+ ctx.Status(500)
+ } else {
+ go models.HookQueue.Add(ctx.Repo.Repository.ID)
+ ctx.Flash.Info(ctx.Tr("repo.settings.webhook.test_delivery_success"))
+ ctx.Status(200)
+ }
+}
+
+func DeleteWebhook(ctx *middleware.Context) {
+ if err := models.DeleteWebhook(ctx.QueryInt64("id")); err != nil {
+ ctx.Flash.Error("DeleteWebhook: " + err.Error())
+ } else {
+ ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
+ }
+
+ ctx.JSON(200, map[string]interface{}{
+ "redirect": ctx.Repo.RepoLink + "/settings/hooks",
+ })
+}