| @@ -5,7 +5,7 @@ Gogs - Go Git Service [ | |||
| ##### Current version: 0.7.31 Beta | |||
| ##### Current version: 0.7.32 Beta | |||
| <table> | |||
| <tr> | |||
| @@ -397,6 +397,7 @@ func runWeb(ctx *cli.Context) { | |||
| m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) | |||
| m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | |||
| m.Get("/:id", repo.WebHooksEdit) | |||
| m.Post("/:id/test", repo.TestWebhook) | |||
| m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) | |||
| m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) | |||
| @@ -597,6 +597,9 @@ settings.hooks_desc = Webhooks are much like basic HTTP POST event triggers. Whe | |||
| settings.webhook_deletion = Delete Webhook | |||
| settings.webhook_deletion_desc = Delete this webhook will remove its information and all delivery history. Do you want to continue? | |||
| settings.webhook_deletion_success = Webhook has been deleted successfully! | |||
| settings.webhook.test_delivery = Test Delivery | |||
| settings.webhook.test_delivery_desc = Send a fake push event delivery to test your webhook settings | |||
| settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. | |||
| settings.webhook.request = Request | |||
| settings.webhook.response = Response | |||
| settings.webhook.headers = Headers | |||
| @@ -17,7 +17,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| const APP_VER = "0.7.31.1205 Beta" | |||
| const APP_VER = "0.7.32.1205 Beta" | |||
| func init() { | |||
| runtime.GOMAXPROCS(runtime.NumCPU()) | |||
| @@ -451,24 +451,9 @@ func CommitRepoAction( | |||
| IsPrivate: repo.IsPrivate, | |||
| }); err != nil { | |||
| return fmt.Errorf("NotifyWatchers: %v", err) | |||
| } | |||
| 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, | |||
| } | |||
| payloadRepo := repo.ComposePayload() | |||
| pusher_email, pusher_name := "", "" | |||
| pusher, err := GetUserByName(userName) | |||
| @@ -494,7 +479,7 @@ func CommitRepoAction( | |||
| commits[i] = &api.PayloadCommit{ | |||
| ID: cmt.Sha1, | |||
| Message: cmt.Message, | |||
| URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1), | |||
| URL: fmt.Sprintf("%s/commit/%s", repo.RepoLink(), cmt.Sha1), | |||
| Author: &api.PayloadAuthor{ | |||
| Name: cmt.AuthorName, | |||
| Email: cmt.AuthorEmail, | |||
| @@ -28,6 +28,7 @@ import ( | |||
| "gopkg.in/ini.v1" | |||
| "github.com/gogits/git-shell" | |||
| api "github.com/gogits/go-gogs-client" | |||
| "github.com/gogits/gogs/modules/base" | |||
| "github.com/gogits/gogs/modules/bindata" | |||
| @@ -380,6 +381,27 @@ func (repo *Repository) SavePatch(index int64, patch []byte) error { | |||
| return nil | |||
| } | |||
| // ComposePayload composes and returns *api.PayloadRepo corresponding to the repository. | |||
| func (repo *Repository) ComposePayload() *api.PayloadRepo { | |||
| cl := repo.CloneLink() | |||
| return &api.PayloadRepo{ | |||
| ID: repo.ID, | |||
| Name: repo.LowerName, | |||
| URL: repo.RepoLink(), | |||
| SSHURL: cl.SSH, | |||
| CloneURL: cl.HTTPS, | |||
| Description: repo.Description, | |||
| Website: repo.Website, | |||
| Watchers: repo.NumWatches, | |||
| Owner: &api.PayloadAuthor{ | |||
| Name: repo.MustOwner().DisplayName(), | |||
| Email: repo.MustOwner().Email, | |||
| UserName: repo.MustOwner().Name, | |||
| }, | |||
| Private: repo.IsPrivate, | |||
| } | |||
| } | |||
| func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) { | |||
| has, err := e.Get(&Repository{ | |||
| OwnerID: u.Id, | |||
| @@ -335,7 +335,7 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) { | |||
| t.ResponseInfo = &HookResponse{} | |||
| if err = json.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil { | |||
| log.Error(3, "Unmarshal[%d]: %v", t.ID, err) | |||
| log.Error(3, "Unmarshal [%d]: %v", t.ID, err) | |||
| } | |||
| } | |||
| } | |||
| @@ -343,7 +343,7 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) { | |||
| func (t *HookTask) MarshalJSON(v interface{}) string { | |||
| p, err := json.Marshal(v) | |||
| if err != nil { | |||
| log.Error(3, "Marshal[%d]: %v", t.ID, err) | |||
| log.Error(3, "Marshal [%d]: %v", t.ID, err) | |||
| } | |||
| return string(p) | |||
| } | |||
| @@ -590,24 +590,24 @@ func DeliverHooks() { | |||
| // Update hook task status. | |||
| for _, t := range tasks { | |||
| if err := UpdateHookTask(t); err != nil { | |||
| log.Error(4, "UpdateHookTask(%d): %v", t.ID, err) | |||
| log.Error(4, "UpdateHookTask [%d]: %v", t.ID, err) | |||
| } | |||
| } | |||
| // Start listening on new hook requests. | |||
| for repoID := range HookQueue.Queue() { | |||
| log.Trace("DeliverHooks[%v]: processing delivery hooks", repoID) | |||
| log.Trace("DeliverHooks [%v]: processing delivery hooks", repoID) | |||
| HookQueue.Remove(repoID) | |||
| tasks = make([]*HookTask, 0, 5) | |||
| if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil { | |||
| log.Error(4, "Get repository(%d) hook tasks: %v", repoID, err) | |||
| log.Error(4, "Get repository [%d] hook tasks: %v", repoID, err) | |||
| continue | |||
| } | |||
| for _, t := range tasks { | |||
| t.deliver() | |||
| if err := UpdateHookTask(t); err != nil { | |||
| log.Error(4, "UpdateHookTask[%d]: %v", t.ID, err) | |||
| log.Error(4, "UpdateHookTask [%d]: %v", t.ID, err) | |||
| continue | |||
| } | |||
| } | |||
| @@ -548,6 +548,19 @@ function initWebhook() { | |||
| $('.events.fields').hide(); | |||
| } | |||
| }); | |||
| // Test delivery | |||
| $('#test-delivery').click(function () { | |||
| var $this = $(this); | |||
| $this.addClass('loading disabled'); | |||
| $.post($this.data('link'), { | |||
| "_csrf": csrf | |||
| }).done( | |||
| setTimeout(function () { | |||
| window.location.href = $this.data('redirect'); | |||
| }, 5000) | |||
| ) | |||
| }); | |||
| } | |||
| @@ -5,14 +5,9 @@ | |||
| package repo | |||
| import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "strings" | |||
| "time" | |||
| "github.com/Unknwon/com" | |||
| "github.com/gogits/gogs/models" | |||
| "github.com/gogits/gogs/modules/auth" | |||
| "github.com/gogits/gogs/modules/base" | |||
| @@ -26,9 +21,6 @@ import ( | |||
| const ( | |||
| SETTINGS_OPTIONS base.TplName = "repo/settings/options" | |||
| COLLABORATION base.TplName = "repo/settings/collaboration" | |||
| HOOKS base.TplName = "repo/settings/hooks" | |||
| HOOK_NEW base.TplName = "repo/settings/hook_new" | |||
| ORG_HOOK_NEW base.TplName = "org/settings/hook_new" | |||
| GITHOOKS base.TplName = "repo/settings/githooks" | |||
| GITHOOK_EDIT base.TplName = "repo/settings/githook_edit" | |||
| DEPLOY_KEYS base.TplName = "repo/settings/deploy_keys" | |||
| @@ -270,330 +262,6 @@ func Collaboration(ctx *middleware.Context) { | |||
| ctx.HTML(200, COLLABORATION) | |||
| } | |||
| 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 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", | |||
| }) | |||
| } | |||
| func parseOwnerAndRepo(ctx *middleware.Context) (*models.User, *models.Repository) { | |||
| owner, err := models.GetUserByName(ctx.Params(":username")) | |||
| if err != nil { | |||
| @@ -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", | |||
| }) | |||
| } | |||
| @@ -1 +1 @@ | |||
| 0.7.31.1205 Beta | |||
| 0.7.32.1205 Beta | |||
| @@ -1,6 +1,12 @@ | |||
| {{if .PageIsSettingsHooksEdit}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.settings.recent_deliveries"}} | |||
| {{if .IsRepositoryAdmin}} | |||
| <div class="ui right"> | |||
| <button class="ui teal tiny button poping up" id="test-delivery" data-content= | |||
| "{{.i18n.Tr "repo.settings.webhook.test_delivery_desc"}}" data-variation="inverted tiny" data-link="{{.Link}}/test" data-redirect="{{.Link}}">{{.i18n.Tr "repo.settings.webhook.test_delivery"}}</button> | |||
| </div> | |||
| {{end}} | |||
| </h4> | |||
| <div class="ui attached table segment"> | |||
| <div class="ui hook history list"> | |||