code.gitea.io/gitea@v1.22.3/services/issue/comments.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issue 5 6 import ( 7 "context" 8 "fmt" 9 10 "code.gitea.io/gitea/models/db" 11 issues_model "code.gitea.io/gitea/models/issues" 12 access_model "code.gitea.io/gitea/models/perm/access" 13 repo_model "code.gitea.io/gitea/models/repo" 14 user_model "code.gitea.io/gitea/models/user" 15 "code.gitea.io/gitea/modules/timeutil" 16 notify_service "code.gitea.io/gitea/services/notify" 17 ) 18 19 // CreateRefComment creates a commit reference comment to issue. 20 func CreateRefComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error { 21 if len(commitSHA) == 0 { 22 return fmt.Errorf("cannot create reference with empty commit SHA") 23 } 24 25 if user_model.IsUserBlockedBy(ctx, doer, issue.PosterID, repo.OwnerID) { 26 if isAdmin, _ := access_model.IsUserRepoAdmin(ctx, repo, doer); !isAdmin { 27 return user_model.ErrBlockedUser 28 } 29 } 30 31 // Check if same reference from same commit has already existed. 32 has, err := db.GetEngine(ctx).Get(&issues_model.Comment{ 33 Type: issues_model.CommentTypeCommitRef, 34 IssueID: issue.ID, 35 CommitSHA: commitSHA, 36 }) 37 if err != nil { 38 return fmt.Errorf("check reference comment: %w", err) 39 } else if has { 40 return nil 41 } 42 43 _, err = issues_model.CreateComment(ctx, &issues_model.CreateCommentOptions{ 44 Type: issues_model.CommentTypeCommitRef, 45 Doer: doer, 46 Repo: repo, 47 Issue: issue, 48 CommitSHA: commitSHA, 49 Content: content, 50 }) 51 return err 52 } 53 54 // CreateIssueComment creates a plain issue comment. 55 func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { 56 if user_model.IsUserBlockedBy(ctx, doer, issue.PosterID, repo.OwnerID) { 57 if isAdmin, _ := access_model.IsUserRepoAdmin(ctx, repo, doer); !isAdmin { 58 return nil, user_model.ErrBlockedUser 59 } 60 } 61 62 comment, err := issues_model.CreateComment(ctx, &issues_model.CreateCommentOptions{ 63 Type: issues_model.CommentTypeComment, 64 Doer: doer, 65 Repo: repo, 66 Issue: issue, 67 Content: content, 68 Attachments: attachments, 69 }) 70 if err != nil { 71 return nil, err 72 } 73 74 mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, doer, comment.Content) 75 if err != nil { 76 return nil, err 77 } 78 79 notify_service.CreateIssueComment(ctx, doer, repo, issue, comment, mentions) 80 81 return comment, nil 82 } 83 84 // UpdateComment updates information of comment. 85 func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error { 86 if err := c.LoadIssue(ctx); err != nil { 87 return err 88 } 89 if err := c.Issue.LoadRepo(ctx); err != nil { 90 return err 91 } 92 93 if user_model.IsUserBlockedBy(ctx, doer, c.Issue.PosterID, c.Issue.Repo.OwnerID) { 94 if isAdmin, _ := access_model.IsUserRepoAdmin(ctx, c.Issue.Repo, doer); !isAdmin { 95 return user_model.ErrBlockedUser 96 } 97 } 98 99 needsContentHistory := c.Content != oldContent && c.Type.HasContentSupport() 100 if needsContentHistory { 101 hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID) 102 if err != nil { 103 return err 104 } 105 if !hasContentHistory { 106 if err = issues_model.SaveIssueContentHistory(ctx, c.PosterID, c.IssueID, c.ID, 107 c.CreatedUnix, oldContent, true); err != nil { 108 return err 109 } 110 } 111 } 112 113 if err := issues_model.UpdateComment(ctx, c, doer); err != nil { 114 return err 115 } 116 117 if needsContentHistory { 118 err := issues_model.SaveIssueContentHistory(ctx, doer.ID, c.IssueID, c.ID, timeutil.TimeStampNow(), c.Content, false) 119 if err != nil { 120 return err 121 } 122 } 123 124 notify_service.UpdateComment(ctx, doer, c, oldContent) 125 126 return nil 127 } 128 129 // DeleteComment deletes the comment 130 func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) error { 131 err := db.WithTx(ctx, func(ctx context.Context) error { 132 return issues_model.DeleteComment(ctx, comment) 133 }) 134 if err != nil { 135 return err 136 } 137 138 notify_service.DeleteComment(ctx, doer, comment) 139 140 return nil 141 }