Skip to content

Commit 3c59d31

Browse files
KN4CK3Rzeripath6543noerwlunny
authored
Add API management for issue/pull and comment attachments (#21783)
Close #14601 Fix #3690 Revive of #14601. Updated to current code, cleanup and added more read/write checks. Signed-off-by: Andrew Thornton <[email protected]> Signed-off-by: Andre Bruch <[email protected]> Co-authored-by: zeripath <[email protected]> Co-authored-by: 6543 <[email protected]> Co-authored-by: Norwin <[email protected]> Co-authored-by: Lunny Xiao <[email protected]>
1 parent 8fb1e53 commit 3c59d31

File tree

21 files changed

+1809
-139
lines changed

21 files changed

+1809
-139
lines changed

models/issues/comment.go

+2
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,8 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
875875
return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
876876
}
877877
}
878+
879+
comment.Attachments = attachments
878880
case CommentTypeReopen, CommentTypeClose:
879881
if err = repo_model.UpdateRepoIssueNumbers(ctx, opts.Issue.RepoID, opts.Issue.IsPull, true); err != nil {
880882
return err

models/migrations/v1_10/v96.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ func DeleteOrphanedAttachments(x *xorm.Engine) error {
3030
}
3131

3232
for {
33-
attachements := make([]Attachment, 0, limit)
33+
attachments := make([]Attachment, 0, limit)
3434
if err := sess.Where("`issue_id` = 0 and (`release_id` = 0 or `release_id` not in (select `id` from `release`))").
3535
Cols("id, uuid").Limit(limit).
3636
Asc("id").
37-
Find(&attachements); err != nil {
37+
Find(&attachments); err != nil {
3838
return err
3939
}
40-
if len(attachements) == 0 {
40+
if len(attachments) == 0 {
4141
return nil
4242
}
4343

4444
ids := make([]int64, 0, limit)
45-
for _, attachment := range attachements {
45+
for _, attachment := range attachments {
4646
ids = append(ids, attachment.ID)
4747
}
4848
if len(ids) > 0 {
@@ -51,13 +51,13 @@ func DeleteOrphanedAttachments(x *xorm.Engine) error {
5151
}
5252
}
5353

54-
for _, attachment := range attachements {
54+
for _, attachment := range attachments {
5555
uuid := attachment.UUID
5656
if err := util.RemoveAll(filepath.Join(setting.Attachment.Path, uuid[0:1], uuid[1:2], uuid)); err != nil {
5757
return err
5858
}
5959
}
60-
if len(attachements) < limit {
60+
if len(attachments) < limit {
6161
return nil
6262
}
6363
}

modules/convert/attachment.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package convert
5+
6+
import (
7+
repo_model "code.gitea.io/gitea/models/repo"
8+
api "code.gitea.io/gitea/modules/structs"
9+
)
10+
11+
// ToAttachment converts models.Attachment to api.Attachment
12+
func ToAttachment(a *repo_model.Attachment) *api.Attachment {
13+
return &api.Attachment{
14+
ID: a.ID,
15+
Name: a.Name,
16+
Created: a.CreatedUnix.AsTime(),
17+
DownloadCount: a.DownloadCount,
18+
Size: a.Size,
19+
UUID: a.UUID,
20+
DownloadURL: a.DownloadURL(),
21+
}
22+
}
23+
24+
func ToAttachments(attachments []*repo_model.Attachment) []*api.Attachment {
25+
converted := make([]*api.Attachment, 0, len(attachments))
26+
for _, attachment := range attachments {
27+
converted = append(converted, ToAttachment(attachment))
28+
}
29+
return converted
30+
}

modules/convert/issue.go

+15-14
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,21 @@ func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
3737
}
3838

3939
apiIssue := &api.Issue{
40-
ID: issue.ID,
41-
URL: issue.APIURL(),
42-
HTMLURL: issue.HTMLURL(),
43-
Index: issue.Index,
44-
Poster: ToUser(issue.Poster, nil),
45-
Title: issue.Title,
46-
Body: issue.Content,
47-
Ref: issue.Ref,
48-
Labels: ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner),
49-
State: issue.State(),
50-
IsLocked: issue.IsLocked,
51-
Comments: issue.NumComments,
52-
Created: issue.CreatedUnix.AsTime(),
53-
Updated: issue.UpdatedUnix.AsTime(),
40+
ID: issue.ID,
41+
URL: issue.APIURL(),
42+
HTMLURL: issue.HTMLURL(),
43+
Index: issue.Index,
44+
Poster: ToUser(issue.Poster, nil),
45+
Title: issue.Title,
46+
Body: issue.Content,
47+
Attachments: ToAttachments(issue.Attachments),
48+
Ref: issue.Ref,
49+
Labels: ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner),
50+
State: issue.State(),
51+
IsLocked: issue.IsLocked,
52+
Comments: issue.NumComments,
53+
Created: issue.CreatedUnix.AsTime(),
54+
Updated: issue.UpdatedUnix.AsTime(),
5455
}
5556

5657
apiIssue.Repo = &api.RepositoryMeta{

modules/convert/issue_comment.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ import (
1616
// ToComment converts a issues_model.Comment to the api.Comment format
1717
func ToComment(c *issues_model.Comment) *api.Comment {
1818
return &api.Comment{
19-
ID: c.ID,
20-
Poster: ToUser(c.Poster, nil),
21-
HTMLURL: c.HTMLURL(),
22-
IssueURL: c.IssueURL(),
23-
PRURL: c.PRURL(),
24-
Body: c.Content,
25-
Created: c.CreatedUnix.AsTime(),
26-
Updated: c.UpdatedUnix.AsTime(),
19+
ID: c.ID,
20+
Poster: ToUser(c.Poster, nil),
21+
HTMLURL: c.HTMLURL(),
22+
IssueURL: c.IssueURL(),
23+
PRURL: c.PRURL(),
24+
Body: c.Content,
25+
Attachments: ToAttachments(c.Attachments),
26+
Created: c.CreatedUnix.AsTime(),
27+
Updated: c.UpdatedUnix.AsTime(),
2728
}
2829
}
2930

modules/convert/release.go

+1-18
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import (
1010

1111
// ToRelease convert a repo_model.Release to api.Release
1212
func ToRelease(r *repo_model.Release) *api.Release {
13-
assets := make([]*api.Attachment, 0)
14-
for _, att := range r.Attachments {
15-
assets = append(assets, ToReleaseAttachment(att))
16-
}
1713
return &api.Release{
1814
ID: r.ID,
1915
TagName: r.TagName,
@@ -29,19 +25,6 @@ func ToRelease(r *repo_model.Release) *api.Release {
2925
CreatedAt: r.CreatedUnix.AsTime(),
3026
PublishedAt: r.CreatedUnix.AsTime(),
3127
Publisher: ToUser(r.Publisher, nil),
32-
Attachments: assets,
33-
}
34-
}
35-
36-
// ToReleaseAttachment converts models.Attachment to api.Attachment
37-
func ToReleaseAttachment(a *repo_model.Attachment) *api.Attachment {
38-
return &api.Attachment{
39-
ID: a.ID,
40-
Name: a.Name,
41-
Created: a.CreatedUnix.AsTime(),
42-
DownloadCount: a.DownloadCount,
43-
Size: a.Size,
44-
UUID: a.UUID,
45-
DownloadURL: a.DownloadURL(),
28+
Attachments: ToAttachments(r.Attachments),
4629
}
4730
}

modules/notification/webhook/webhook.go

+5
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ func (m *webhookNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues
314314
}
315315

316316
func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) {
317+
if err := issue.LoadRepo(ctx); err != nil {
318+
log.Error("LoadRepo: %v", err)
319+
return
320+
}
321+
317322
mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo)
318323
var err error
319324
if issue.IsPull {

modules/structs/issue.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,19 @@ type RepositoryMeta struct {
4141
// Issue represents an issue in a repository
4242
// swagger:model
4343
type Issue struct {
44-
ID int64 `json:"id"`
45-
URL string `json:"url"`
46-
HTMLURL string `json:"html_url"`
47-
Index int64 `json:"number"`
48-
Poster *User `json:"user"`
49-
OriginalAuthor string `json:"original_author"`
50-
OriginalAuthorID int64 `json:"original_author_id"`
51-
Title string `json:"title"`
52-
Body string `json:"body"`
53-
Ref string `json:"ref"`
54-
Labels []*Label `json:"labels"`
55-
Milestone *Milestone `json:"milestone"`
44+
ID int64 `json:"id"`
45+
URL string `json:"url"`
46+
HTMLURL string `json:"html_url"`
47+
Index int64 `json:"number"`
48+
Poster *User `json:"user"`
49+
OriginalAuthor string `json:"original_author"`
50+
OriginalAuthorID int64 `json:"original_author_id"`
51+
Title string `json:"title"`
52+
Body string `json:"body"`
53+
Ref string `json:"ref"`
54+
Attachments []*Attachment `json:"assets"`
55+
Labels []*Label `json:"labels"`
56+
Milestone *Milestone `json:"milestone"`
5657
// deprecated
5758
Assignee *User `json:"assignee"`
5859
Assignees []*User `json:"assignees"`

modules/structs/issue_comment.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import (
99

1010
// Comment represents a comment on a commit or issue
1111
type Comment struct {
12-
ID int64 `json:"id"`
13-
HTMLURL string `json:"html_url"`
14-
PRURL string `json:"pull_request_url"`
15-
IssueURL string `json:"issue_url"`
16-
Poster *User `json:"user"`
17-
OriginalAuthor string `json:"original_author"`
18-
OriginalAuthorID int64 `json:"original_author_id"`
19-
Body string `json:"body"`
12+
ID int64 `json:"id"`
13+
HTMLURL string `json:"html_url"`
14+
PRURL string `json:"pull_request_url"`
15+
IssueURL string `json:"issue_url"`
16+
Poster *User `json:"user"`
17+
OriginalAuthor string `json:"original_author"`
18+
OriginalAuthorID int64 `json:"original_author_id"`
19+
Body string `json:"body"`
20+
Attachments []*Attachment `json:"assets"`
2021
// swagger:strfmt date-time
2122
Created time.Time `json:"created_at"`
2223
// swagger:strfmt date-time

routers/api/v1/api.go

+25
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,13 @@ func mustNotBeArchived(ctx *context.APIContext) {
567567
}
568568
}
569569

570+
func mustEnableAttachments(ctx *context.APIContext) {
571+
if !setting.Attachment.Enabled {
572+
ctx.NotFound()
573+
return
574+
}
575+
}
576+
570577
// bind binding an obj to a func(ctx *context.APIContext)
571578
func bind(obj interface{}) http.HandlerFunc {
572579
tp := reflect.TypeOf(obj)
@@ -892,6 +899,15 @@ func Routes(ctx gocontext.Context) *web.Route {
892899
Get(repo.GetIssueCommentReactions).
893900
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
894901
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
902+
m.Group("/assets", func() {
903+
m.Combo("").
904+
Get(repo.ListIssueCommentAttachments).
905+
Post(reqToken(), mustNotBeArchived, repo.CreateIssueCommentAttachment)
906+
m.Combo("/{asset}").
907+
Get(repo.GetIssueCommentAttachment).
908+
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment).
909+
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueCommentAttachment)
910+
}, mustEnableAttachments)
895911
})
896912
})
897913
m.Group("/{index}", func() {
@@ -935,6 +951,15 @@ func Routes(ctx gocontext.Context) *web.Route {
935951
Get(repo.GetIssueReactions).
936952
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueReaction).
937953
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
954+
m.Group("/assets", func() {
955+
m.Combo("").
956+
Get(repo.ListIssueAttachments).
957+
Post(reqToken(), mustNotBeArchived, repo.CreateIssueAttachment)
958+
m.Combo("/{asset}").
959+
Get(repo.GetIssueAttachment).
960+
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
961+
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueAttachment)
962+
}, mustEnableAttachments)
938963
})
939964
}, mustEnableIssuesOrPulls)
940965
m.Group("/labels", func() {

0 commit comments

Comments
 (0)