* Webhooks for repo creation/deletion * add createHookTask * Add handles for GetSlackPayload and GetDiscordPayloadtags/v1.21.12.1
| @@ -835,8 +835,8 @@ func wikiRemoteURL(remote string) string { | |||
| } | |||
| // MigrateRepository migrates a existing repository from other project hosting. | |||
| func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) { | |||
| repo, err := CreateRepository(u, CreateRepoOptions{ | |||
| func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, error) { | |||
| repo, err := CreateRepository(doer, u, CreateRepoOptions{ | |||
| Name: opts.Name, | |||
| Description: opts.Description, | |||
| IsPrivate: opts.IsPrivate, | |||
| @@ -1202,7 +1202,7 @@ func IsUsableRepoName(name string) error { | |||
| return isUsableName(reservedRepoNames, reservedRepoPatterns, name) | |||
| } | |||
| func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) { | |||
| func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err error) { | |||
| if err = IsUsableRepoName(repo.Name); err != nil { | |||
| return err | |||
| } | |||
| @@ -1249,7 +1249,15 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) { | |||
| return fmt.Errorf("getOwnerTeam: %v", err) | |||
| } else if err = t.addRepository(e, repo); err != nil { | |||
| return fmt.Errorf("addRepository: %v", err) | |||
| } else if err = prepareWebhooks(e, repo, HookEventRepository, &api.RepositoryPayload{ | |||
| Action: api.HookRepoCreated, | |||
| Repository: repo.APIFormat(AccessModeOwner), | |||
| Organization: u.APIFormat(), | |||
| Sender: doer.APIFormat(), | |||
| }); err != nil { | |||
| return fmt.Errorf("prepareWebhooks: %v", err) | |||
| } | |||
| go HookQueue.Add(repo.ID) | |||
| } else { | |||
| // Organization automatically called this in addRepository method. | |||
| if err = repo.recalculateAccesses(e); err != nil { | |||
| @@ -1266,8 +1274,8 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) { | |||
| return nil | |||
| } | |||
| // CreateRepository creates a repository for given user or organization. | |||
| func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) { | |||
| // CreateRepository creates a repository for the user/organization u. | |||
| func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err error) { | |||
| if !u.CanCreateRepo() { | |||
| return nil, ErrReachLimitOfRepo{u.MaxRepoCreation} | |||
| } | |||
| @@ -1287,7 +1295,7 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error | |||
| return nil, err | |||
| } | |||
| if err = createRepository(sess, u, repo); err != nil { | |||
| if err = createRepository(sess, doer, u, repo); err != nil { | |||
| return nil, err | |||
| } | |||
| @@ -1623,7 +1631,7 @@ func UpdateRepositoryUnits(repo *Repository, units []RepoUnit) (err error) { | |||
| } | |||
| // DeleteRepository deletes a repository for a user or organization. | |||
| func DeleteRepository(uid, repoID int64) error { | |||
| func DeleteRepository(doer *User, uid, repoID int64) error { | |||
| // In case is a organization. | |||
| org, err := GetUserByID(uid) | |||
| if err != nil { | |||
| @@ -1781,6 +1789,18 @@ func DeleteRepository(uid, repoID int64) error { | |||
| return fmt.Errorf("Commit: %v", err) | |||
| } | |||
| if org.IsOrganization() { | |||
| if err = PrepareWebhooks(repo, HookEventRepository, &api.RepositoryPayload{ | |||
| Action: api.HookRepoDeleted, | |||
| Repository: repo.APIFormat(AccessModeOwner), | |||
| Organization: org.APIFormat(), | |||
| Sender: doer.APIFormat(), | |||
| }); err != nil { | |||
| return err | |||
| } | |||
| go HookQueue.Add(repo.ID) | |||
| } | |||
| return nil | |||
| } | |||
| @@ -1974,7 +1994,7 @@ func gatherMissingRepoRecords() ([]*Repository, error) { | |||
| } | |||
| // DeleteMissingRepositories deletes all repository records that lost Git files. | |||
| func DeleteMissingRepositories() error { | |||
| func DeleteMissingRepositories(doer *User) error { | |||
| repos, err := gatherMissingRepoRecords() | |||
| if err != nil { | |||
| return fmt.Errorf("gatherMissingRepoRecords: %v", err) | |||
| @@ -1986,7 +2006,7 @@ func DeleteMissingRepositories() error { | |||
| for _, repo := range repos { | |||
| log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID) | |||
| if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil { | |||
| if err := DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil { | |||
| if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil { | |||
| return fmt.Errorf("CreateRepositoryNotice: %v", err) | |||
| } | |||
| @@ -2226,7 +2246,7 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) { | |||
| } | |||
| // ForkRepository forks a repository | |||
| func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) { | |||
| func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) { | |||
| forkedRepo, err := oldRepo.GetUserFork(u.ID) | |||
| if err != nil { | |||
| return nil, err | |||
| @@ -2256,7 +2276,7 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit | |||
| return nil, err | |||
| } | |||
| if err = createRepository(sess, u, repo); err != nil { | |||
| if err = createRepository(sess, doer, u, repo); err != nil { | |||
| return nil, err | |||
| } | |||
| @@ -118,13 +118,12 @@ func TestGetUserFork(t *testing.T) { | |||
| func TestForkRepository(t *testing.T) { | |||
| assert.NoError(t, PrepareTestDatabase()) | |||
| // User13 has repo 11 forked from repo10 | |||
| repo, err := GetRepositoryByID(10) | |||
| assert.NoError(t, err) | |||
| assert.NotNil(t, repo) | |||
| // user 13 has already forked repo10 | |||
| user := AssertExistsAndLoadBean(t, &User{ID: 13}).(*User) | |||
| repo := AssertExistsAndLoadBean(t, &Repository{ID: 10}).(*Repository) | |||
| repo, err = ForkRepository(&User{ID: 13}, repo, "test", "test") | |||
| assert.Nil(t, repo) | |||
| fork, err := ForkRepository(user, user, repo, "test", "test") | |||
| assert.Nil(t, fork) | |||
| assert.Error(t, err) | |||
| assert.True(t, IsErrRepoAlreadyExist(err)) | |||
| } | |||
| @@ -68,6 +68,7 @@ type HookEvents struct { | |||
| Create bool `json:"create"` | |||
| Push bool `json:"push"` | |||
| PullRequest bool `json:"pull_request"` | |||
| Repository bool `json:"repository"` | |||
| } | |||
| // HookEvent represents events that will delivery hook. | |||
| @@ -188,6 +189,12 @@ func (w *Webhook) HasPullRequestEvent() bool { | |||
| (w.ChooseEvents && w.HookEvents.PullRequest) | |||
| } | |||
| // HasRepositoryEvent returns if hook enabled repository event. | |||
| func (w *Webhook) HasRepositoryEvent() bool { | |||
| return w.SendEverything || | |||
| (w.ChooseEvents && w.HookEvents.Repository) | |||
| } | |||
| // EventsArray returns an array of hook events | |||
| func (w *Webhook) EventsArray() []string { | |||
| events := make([]string, 0, 3) | |||
| @@ -246,8 +253,12 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) { | |||
| // GetActiveWebhooksByRepoID returns all active webhooks of repository. | |||
| func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) { | |||
| return getActiveWebhooksByRepoID(x, repoID) | |||
| } | |||
| func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) { | |||
| webhooks := make([]*Webhook, 0, 5) | |||
| return webhooks, x.Where("is_active=?", true). | |||
| return webhooks, e.Where("is_active=?", true). | |||
| Find(&webhooks, &Webhook{RepoID: repoID}) | |||
| } | |||
| @@ -259,7 +270,11 @@ func GetWebhooksByRepoID(repoID int64) ([]*Webhook, error) { | |||
| // GetActiveWebhooksByOrgID returns all active webhooks for an organization. | |||
| func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) { | |||
| err = x. | |||
| return getActiveWebhooksByOrgID(x, orgID) | |||
| } | |||
| func getActiveWebhooksByOrgID(e Engine, orgID int64) (ws []*Webhook, err error) { | |||
| err = e. | |||
| Where("org_id=?", orgID). | |||
| And("is_active=?", true). | |||
| Find(&ws) | |||
| @@ -379,6 +394,7 @@ const ( | |||
| HookEventCreate HookEventType = "create" | |||
| HookEventPush HookEventType = "push" | |||
| HookEventPullRequest HookEventType = "pull_request" | |||
| HookEventRepository HookEventType = "repository" | |||
| ) | |||
| // HookRequest represents hook task request information. | |||
| @@ -479,13 +495,17 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) { | |||
| // CreateHookTask creates a new hook task, | |||
| // it handles conversion from Payload to PayloadContent. | |||
| func CreateHookTask(t *HookTask) error { | |||
| return createHookTask(x, t) | |||
| } | |||
| func createHookTask(e Engine, t *HookTask) error { | |||
| data, err := t.Payloader.JSONPayload() | |||
| if err != nil { | |||
| return err | |||
| } | |||
| t.UUID = gouuid.NewV4().String() | |||
| t.PayloadContent = string(data) | |||
| _, err = x.Insert(t) | |||
| _, err = e.Insert(t) | |||
| return err | |||
| } | |||
| @@ -497,6 +517,10 @@ func UpdateHookTask(t *HookTask) error { | |||
| // PrepareWebhook adds special webhook to task queue for given payload. | |||
| func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error { | |||
| return prepareWebhook(x, w, repo, event, p) | |||
| } | |||
| func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error { | |||
| switch event { | |||
| case HookEventCreate: | |||
| if !w.HasCreateEvent() { | |||
| @@ -510,6 +534,10 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay | |||
| if !w.HasPullRequestEvent() { | |||
| return nil | |||
| } | |||
| case HookEventRepository: | |||
| if !w.HasRepositoryEvent() { | |||
| return nil | |||
| } | |||
| } | |||
| var payloader api.Payloader | |||
| @@ -531,7 +559,7 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay | |||
| payloader = p | |||
| } | |||
| if err = CreateHookTask(&HookTask{ | |||
| if err = createHookTask(e, &HookTask{ | |||
| RepoID: repo.ID, | |||
| HookID: w.ID, | |||
| Type: w.HookTaskType, | |||
| @@ -548,15 +576,19 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay | |||
| // PrepareWebhooks adds new webhooks to task queue for given payload. | |||
| func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error { | |||
| ws, err := GetActiveWebhooksByRepoID(repo.ID) | |||
| return prepareWebhooks(x, repo, event, p) | |||
| } | |||
| func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error { | |||
| ws, err := getActiveWebhooksByRepoID(e, repo.ID) | |||
| if err != nil { | |||
| return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err) | |||
| } | |||
| // check if repo belongs to org and append additional webhooks | |||
| if repo.MustOwner().IsOrganization() { | |||
| if repo.mustOwner(e).IsOrganization() { | |||
| // get hooks for org | |||
| orgHooks, err := GetActiveWebhooksByOrgID(repo.OwnerID) | |||
| orgHooks, err := getActiveWebhooksByOrgID(e, repo.OwnerID) | |||
| if err != nil { | |||
| return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err) | |||
| } | |||
| @@ -568,7 +600,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err | |||
| } | |||
| for _, w := range ws { | |||
| if err = PrepareWebhook(w, repo, event, p); err != nil { | |||
| if err = prepareWebhook(e, w, repo, event, p); err != nil { | |||
| return err | |||
| } | |||
| } | |||
| @@ -228,6 +228,37 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) | |||
| }, nil | |||
| } | |||
| func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*DiscordPayload, error) { | |||
| var title, url string | |||
| var color int | |||
| switch p.Action { | |||
| case api.HookRepoCreated: | |||
| title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName) | |||
| url = p.Repository.HTMLURL | |||
| color = successColor | |||
| case api.HookRepoDeleted: | |||
| title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) | |||
| color = warnColor | |||
| } | |||
| return &DiscordPayload{ | |||
| Username: meta.Username, | |||
| AvatarURL: meta.IconURL, | |||
| Embeds: []DiscordEmbed{ | |||
| { | |||
| Title: title, | |||
| URL: url, | |||
| Color: color, | |||
| Author: DiscordEmbedAuthor{ | |||
| Name: p.Sender.UserName, | |||
| URL: setting.AppURL + p.Sender.UserName, | |||
| IconURL: p.Sender.AvatarURL, | |||
| }, | |||
| }, | |||
| }, | |||
| }, nil | |||
| } | |||
| // GetDiscordPayload converts a discord webhook into a DiscordPayload | |||
| func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) { | |||
| s := new(DiscordPayload) | |||
| @@ -244,6 +275,8 @@ func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*Disc | |||
| return getDiscordPushPayload(p.(*api.PushPayload), discord) | |||
| case HookEventPullRequest: | |||
| return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) | |||
| case HookEventRepository: | |||
| return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) | |||
| } | |||
| return s, nil | |||
| @@ -189,6 +189,30 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S | |||
| }, nil | |||
| } | |||
| func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) { | |||
| senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) | |||
| var text, title, attachmentText string | |||
| switch p.Action { | |||
| case api.HookRepoCreated: | |||
| text = fmt.Sprintf("[%s] Repository created by %s", p.Repository.FullName, senderLink) | |||
| title = p.Repository.HTMLURL | |||
| case api.HookRepoDeleted: | |||
| text = fmt.Sprintf("[%s] Repository deleted by %s", p.Repository.FullName, senderLink) | |||
| } | |||
| return &SlackPayload{ | |||
| Channel: slack.Channel, | |||
| Text: text, | |||
| Username: slack.Username, | |||
| IconURL: slack.IconURL, | |||
| Attachments: []SlackAttachment{{ | |||
| Color: slack.Color, | |||
| Title: title, | |||
| Text: attachmentText, | |||
| }}, | |||
| }, nil | |||
| } | |||
| // GetSlackPayload converts a slack webhook into a SlackPayload | |||
| func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) { | |||
| s := new(SlackPayload) | |||
| @@ -205,6 +229,8 @@ func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackP | |||
| return getSlackPushPayload(p.(*api.PushPayload), slack) | |||
| case HookEventPullRequest: | |||
| return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) | |||
| case HookEventRepository: | |||
| return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) | |||
| } | |||
| return s, nil | |||
| @@ -124,6 +124,7 @@ type WebhookForm struct { | |||
| Create bool | |||
| Push bool | |||
| PullRequest bool | |||
| Repository bool | |||
| Active bool | |||
| } | |||
| @@ -892,6 +892,8 @@ settings.event_pull_request = Pull Request | |||
| settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized. | |||
| settings.event_push = Push | |||
| settings.event_push_desc = Git push to a repository | |||
| settings.event_repository = Repository | |||
| settings.event_repository_desc = Repository created or deleted | |||
| settings.active = Active | |||
| settings.active_helper = Information about the event which triggered the hook will be sent as well. | |||
| settings.add_hook_success = New webhook has been added. | |||
| @@ -145,7 +145,7 @@ func Dashboard(ctx *context.Context) { | |||
| err = models.DeleteRepositoryArchives() | |||
| case cleanMissingRepos: | |||
| success = ctx.Tr("admin.dashboard.delete_missing_repos_success") | |||
| err = models.DeleteMissingRepositories() | |||
| err = models.DeleteMissingRepositories(ctx.User) | |||
| case gitGCRepos: | |||
| success = ctx.Tr("admin.dashboard.git_gc_repos_success") | |||
| err = models.GitGcRepos() | |||
| @@ -39,7 +39,7 @@ func DeleteRepo(ctx *context.Context) { | |||
| return | |||
| } | |||
| if err := models.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil { | |||
| if err := models.DeleteRepository(ctx.User, repo.MustOwner().ID, repo.ID); err != nil { | |||
| ctx.Handle(500, "DeleteRepository", err) | |||
| return | |||
| } | |||
| @@ -73,7 +73,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) { | |||
| } | |||
| forker = org | |||
| } | |||
| fork, err := models.ForkRepository(forker, repo, repo.Name, repo.Description) | |||
| fork, err := models.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description) | |||
| if err != nil { | |||
| ctx.Error(500, "ForkRepository", err) | |||
| return | |||
| @@ -105,7 +105,7 @@ func Search(ctx *context.APIContext) { | |||
| // CreateUserRepo create a repository for a user | |||
| func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) { | |||
| repo, err := models.CreateRepository(owner, models.CreateRepoOptions{ | |||
| repo, err := models.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ | |||
| Name: opt.Name, | |||
| Description: opt.Description, | |||
| Gitignores: opt.Gitignores, | |||
| @@ -121,7 +121,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR | |||
| ctx.Error(422, "", err) | |||
| } else { | |||
| if repo != nil { | |||
| if err = models.DeleteRepository(ctx.User.ID, repo.ID); err != nil { | |||
| if err = models.DeleteRepository(ctx.User, ctx.User.ID, repo.ID); err != nil { | |||
| log.Error(4, "DeleteRepository: %v", err) | |||
| } | |||
| } | |||
| @@ -254,7 +254,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { | |||
| return | |||
| } | |||
| repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{ | |||
| repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{ | |||
| Name: form.RepoName, | |||
| Description: form.Description, | |||
| IsPrivate: form.Private || setting.Repository.ForcePrivate, | |||
| @@ -263,7 +263,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { | |||
| }) | |||
| if err != nil { | |||
| if repo != nil { | |||
| if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil { | |||
| if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil { | |||
| log.Error(4, "DeleteRepository: %v", errDelete) | |||
| } | |||
| } | |||
| @@ -345,7 +345,7 @@ func Delete(ctx *context.APIContext) { | |||
| return | |||
| } | |||
| if err := models.DeleteRepository(owner.ID, repo.ID); err != nil { | |||
| if err := models.DeleteRepository(ctx.User, owner.ID, repo.ID); err != nil { | |||
| ctx.Error(500, "DeleteRepository", err) | |||
| return | |||
| } | |||
| @@ -125,7 +125,7 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) { | |||
| } | |||
| } | |||
| repo, err := models.ForkRepository(ctxUser, forkRepo, form.RepoName, form.Description) | |||
| repo, err := models.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description) | |||
| if err != nil { | |||
| ctx.Data["Err_RepoName"] = true | |||
| switch { | |||
| @@ -127,7 +127,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
| return | |||
| } | |||
| repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{ | |||
| repo, err := models.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | |||
| Name: form.RepoName, | |||
| Description: form.Description, | |||
| Gitignores: form.Gitignores, | |||
| @@ -143,7 +143,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
| } | |||
| if repo != nil { | |||
| if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil { | |||
| if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil { | |||
| log.Error(4, "DeleteRepository: %v", errDelete) | |||
| } | |||
| } | |||
| @@ -204,7 +204,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||
| return | |||
| } | |||
| repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{ | |||
| repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{ | |||
| Name: form.RepoName, | |||
| Description: form.Description, | |||
| IsPrivate: form.Private || setting.Repository.ForcePrivate, | |||
| @@ -218,7 +218,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||
| } | |||
| if repo != nil { | |||
| if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil { | |||
| if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil { | |||
| log.Error(4, "DeleteRepository: %v", errDelete) | |||
| } | |||
| } | |||
| @@ -314,7 +314,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
| } | |||
| } | |||
| if err := models.DeleteRepository(ctx.Repo.Owner.ID, repo.ID); err != nil { | |||
| if err := models.DeleteRepository(ctx.User, ctx.Repo.Owner.ID, repo.ID); err != nil { | |||
| ctx.Handle(500, "DeleteRepository", err) | |||
| return | |||
| } | |||
| @@ -121,6 +121,7 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent { | |||
| Create: form.Create, | |||
| Push: form.Push, | |||
| PullRequest: form.PullRequest, | |||
| Repository: form.Repository, | |||
| }, | |||
| } | |||
| } | |||
| @@ -52,6 +52,16 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <!-- Repository --> | |||
| <div class="seven wide column"> | |||
| <div class="field"> | |||
| <div class="ui checkbox"> | |||
| <input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}> | |||
| <label>{{.i18n.Tr "repo.settings.event_repository"}}</label> | |||
| <span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||