diff --git a/models/issue_comment.go b/models/issue_comment.go index 6786032f41..e8043c1ec7 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -169,7 +169,7 @@ func (c *Comment) loadIssue(e Engine) (err error) { } func (c *Comment) loadPoster(e Engine) (err error) { - if c.Poster != nil { + if c.PosterID <= 0 || c.Poster != nil { return nil } @@ -338,21 +338,7 @@ func (c *Comment) LoadMilestone() error { // LoadPoster loads comment poster func (c *Comment) LoadPoster() error { - if c.PosterID <= 0 || c.Poster != nil { - return nil - } - - var err error - c.Poster, err = getUserByID(x, c.PosterID) - if err != nil { - if IsErrUserNotExist(err) { - c.PosterID = -1 - c.Poster = NewGhostUser() - } else { - log.Error("getUserByID[%d]: %v", c.ID, err) - } - } - return nil + return c.loadPoster(x) } // LoadAttachments loads attachments @@ -440,7 +426,7 @@ func (c *Comment) checkInvalidation(doer *User, repo *git.Repository, branch str } if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() { c.Invalidated = true - return UpdateComment(doer, c, "") + return UpdateComment(c, doer) } return nil } @@ -811,35 +797,6 @@ func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) { return comment, nil } -// CreateIssueComment creates a plain issue comment. -func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) { - comment, err := CreateComment(&CreateCommentOptions{ - Type: CommentTypeComment, - Doer: doer, - Repo: repo, - Issue: issue, - Content: content, - Attachments: attachments, - }) - if err != nil { - return nil, fmt.Errorf("CreateComment: %v", err) - } - - mode, _ := AccessLevel(doer, repo) - if err = PrepareWebhooks(repo, HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentCreated, - Issue: issue.APIFormat(), - Comment: comment.APIFormat(), - Repository: repo.APIFormat(mode), - Sender: doer.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) - } else { - go HookQueue.Add(repo.ID) - } - return comment, nil -} - // CreateRefComment creates a commit reference comment to issue. func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commitSHA string) error { if len(commitSHA) == 0 { @@ -928,7 +885,7 @@ func FindComments(opts FindCommentsOptions) ([]*Comment, error) { } // UpdateComment updates information of comment. -func UpdateComment(doer *User, c *Comment, oldContent string) error { +func UpdateComment(c *Comment, doer *User) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { @@ -950,38 +907,12 @@ func UpdateComment(doer *User, c *Comment, oldContent string) error { if err := sess.Commit(); err != nil { return fmt.Errorf("Commit: %v", err) } - sess.Close() - - if err := c.LoadPoster(); err != nil { - return err - } - if err := c.Issue.LoadAttributes(); err != nil { - return err - } - - mode, _ := AccessLevel(doer, c.Issue.Repo) - if err := PrepareWebhooks(c.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentEdited, - Issue: c.Issue.APIFormat(), - Comment: c.APIFormat(), - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - Repository: c.Issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) - } else { - go HookQueue.Add(c.Issue.Repo.ID) - } return nil } // DeleteComment deletes the comment -func DeleteComment(doer *User, comment *Comment) error { +func DeleteComment(comment *Comment, doer *User) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { @@ -1007,43 +938,7 @@ func DeleteComment(doer *User, comment *Comment) error { return err } - if err := sess.Commit(); err != nil { - return err - } - sess.Close() - - if err := comment.LoadPoster(); err != nil { - return err - } - if err := comment.LoadIssue(); err != nil { - return err - } - - if err := comment.Issue.LoadAttributes(); err != nil { - return err - } - if err := comment.loadPoster(x); err != nil { - return err - } - if err := comment.neuterCrossReferences(x); err != nil { - return err - } - - mode, _ := AccessLevel(doer, comment.Issue.Repo) - - if err := PrepareWebhooks(comment.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentDeleted, - Issue: comment.Issue.APIFormat(), - Comment: comment.APIFormat(), - Repository: comment.Issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) - } else { - go HookQueue.Add(comment.Issue.Repo.ID) - } - - return nil + return sess.Commit() } // CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 18fa1d3eb2..60796031a5 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/notification" api "code.gitea.io/gitea/modules/structs" + comment_service "code.gitea.io/gitea/services/comments" ) // ListIssueComments list all the comments of an issue @@ -189,7 +190,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti return } - comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil) + comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil) if err != nil { ctx.Error(500, "CreateIssueComment", err) return @@ -299,7 +300,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) oldContent := comment.Content comment.Content = form.Body - if err := models.UpdateComment(ctx.User, comment, oldContent); err != nil { + if err := comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil { ctx.Error(500, "UpdateComment", err) return } @@ -390,7 +391,7 @@ func deleteIssueComment(ctx *context.APIContext) { return } - if err = models.DeleteComment(ctx.User, comment); err != nil { + if err = comment_service.DeleteComment(comment, ctx.User); err != nil { ctx.Error(500, "DeleteCommentByID", err) return } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index b9083e20e9..1be0b408a6 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + comment_service "code.gitea.io/gitea/services/comments" milestone_service "code.gitea.io/gitea/services/milestone" "github.com/unknwon/com" @@ -1299,7 +1300,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) { return } - comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments) + comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments) if err != nil { ctx.ServerError("CreateIssueComment", err) return @@ -1339,7 +1340,7 @@ func UpdateCommentContent(ctx *context.Context) { }) return } - if err = models.UpdateComment(ctx.User, comment, oldContent); err != nil { + if err = comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil { ctx.ServerError("UpdateComment", err) return } @@ -1372,7 +1373,7 @@ func DeleteComment(ctx *context.Context) { return } - if err = models.DeleteComment(ctx.User, comment); err != nil { + if err = models.DeleteComment(comment, ctx.User); err != nil { ctx.ServerError("DeleteCommentByID", err) return } diff --git a/services/comments/comments.go b/services/comments/comments.go index bd261ff0a5..e8448e9065 100644 --- a/services/comments/comments.go +++ b/services/comments/comments.go @@ -11,10 +11,41 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/gitdiff" ) +// CreateIssueComment creates a plain issue comment. +func CreateIssueComment(doer *models.User, repo *models.Repository, issue *models.Issue, content string, attachments []string) (*models.Comment, error) { + comment, err := models.CreateComment(&models.CreateCommentOptions{ + Type: models.CommentTypeComment, + Doer: doer, + Repo: repo, + Issue: issue, + Content: content, + Attachments: attachments, + }) + if err != nil { + return nil, err + } + + mode, _ := models.AccessLevel(doer, repo) + if err = models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentCreated, + Issue: issue.APIFormat(), + Comment: comment.APIFormat(), + Repository: repo.APIFormat(mode), + Sender: doer.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } else { + go models.HookQueue.Add(repo.ID) + } + return comment, nil +} + // CreateCodeComment creates a plain code comment at the specified line / path func CreateCodeComment(doer *models.User, repo *models.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) { var commitID, patch string @@ -67,3 +98,75 @@ func CreateCodeComment(doer *models.User, repo *models.Repository, issue *models Patch: patch, }) } + +// UpdateComment updates information of comment. +func UpdateComment(c *models.Comment, doer *models.User, oldContent string) error { + if err := models.UpdateComment(c, doer); err != nil { + return err + } + + if err := c.LoadPoster(); err != nil { + return err + } + if err := c.LoadIssue(); err != nil { + return err + } + + if err := c.Issue.LoadAttributes(); err != nil { + return err + } + + mode, _ := models.AccessLevel(doer, c.Issue.Repo) + if err := models.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentEdited, + Issue: c.Issue.APIFormat(), + Comment: c.APIFormat(), + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Repository: c.Issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) + } else { + go models.HookQueue.Add(c.Issue.Repo.ID) + } + + return nil +} + +// DeleteComment deletes the comment +func DeleteComment(comment *models.Comment, doer *models.User) error { + if err := models.DeleteComment(comment, doer); err != nil { + return err + } + + if err := comment.LoadPoster(); err != nil { + return err + } + if err := comment.LoadIssue(); err != nil { + return err + } + + if err := comment.Issue.LoadAttributes(); err != nil { + return err + } + + mode, _ := models.AccessLevel(doer, comment.Issue.Repo) + + if err := models.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentDeleted, + Issue: comment.Issue.APIFormat(), + Comment: comment.APIFormat(), + Repository: comment.Issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } else { + go models.HookQueue.Add(comment.Issue.Repo.ID) + } + + return nil +}