Skip to content

Commit

Permalink
Add API management for issue/pull and comment attachments (#21783)
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
5 people authored Dec 9, 2022
1 parent 8fb1e53 commit 3c59d31
Show file tree
Hide file tree
Showing 21 changed files with 1,809 additions and 139 deletions.
2 changes: 2 additions & 0 deletions models/issues/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,8 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
}
}

comment.Attachments = attachments
case CommentTypeReopen, CommentTypeClose:
if err = repo_model.UpdateRepoIssueNumbers(ctx, opts.Issue.RepoID, opts.Issue.IsPull, true); err != nil {
return err
Expand Down
12 changes: 6 additions & 6 deletions models/migrations/v1_10/v96.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ func DeleteOrphanedAttachments(x *xorm.Engine) error {
}

for {
attachements := make([]Attachment, 0, limit)
attachments := make([]Attachment, 0, limit)
if err := sess.Where("`issue_id` = 0 and (`release_id` = 0 or `release_id` not in (select `id` from `release`))").
Cols("id, uuid").Limit(limit).
Asc("id").
Find(&attachements); err != nil {
Find(&attachments); err != nil {
return err
}
if len(attachements) == 0 {
if len(attachments) == 0 {
return nil
}

ids := make([]int64, 0, limit)
for _, attachment := range attachements {
for _, attachment := range attachments {
ids = append(ids, attachment.ID)
}
if len(ids) > 0 {
Expand All @@ -51,13 +51,13 @@ func DeleteOrphanedAttachments(x *xorm.Engine) error {
}
}

for _, attachment := range attachements {
for _, attachment := range attachments {
uuid := attachment.UUID
if err := util.RemoveAll(filepath.Join(setting.Attachment.Path, uuid[0:1], uuid[1:2], uuid)); err != nil {
return err
}
}
if len(attachements) < limit {
if len(attachments) < limit {
return nil
}
}
Expand Down
30 changes: 30 additions & 0 deletions modules/convert/attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package convert

import (
repo_model "code.gitea.io/gitea/models/repo"
api "code.gitea.io/gitea/modules/structs"
)

// ToAttachment converts models.Attachment to api.Attachment
func ToAttachment(a *repo_model.Attachment) *api.Attachment {
return &api.Attachment{
ID: a.ID,
Name: a.Name,
Created: a.CreatedUnix.AsTime(),
DownloadCount: a.DownloadCount,
Size: a.Size,
UUID: a.UUID,
DownloadURL: a.DownloadURL(),
}
}

func ToAttachments(attachments []*repo_model.Attachment) []*api.Attachment {
converted := make([]*api.Attachment, 0, len(attachments))
for _, attachment := range attachments {
converted = append(converted, ToAttachment(attachment))
}
return converted
}
29 changes: 15 additions & 14 deletions modules/convert/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,21 @@ func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
}

apiIssue := &api.Issue{
ID: issue.ID,
URL: issue.APIURL(),
HTMLURL: issue.HTMLURL(),
Index: issue.Index,
Poster: ToUser(issue.Poster, nil),
Title: issue.Title,
Body: issue.Content,
Ref: issue.Ref,
Labels: ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner),
State: issue.State(),
IsLocked: issue.IsLocked,
Comments: issue.NumComments,
Created: issue.CreatedUnix.AsTime(),
Updated: issue.UpdatedUnix.AsTime(),
ID: issue.ID,
URL: issue.APIURL(),
HTMLURL: issue.HTMLURL(),
Index: issue.Index,
Poster: ToUser(issue.Poster, nil),
Title: issue.Title,
Body: issue.Content,
Attachments: ToAttachments(issue.Attachments),
Ref: issue.Ref,
Labels: ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner),
State: issue.State(),
IsLocked: issue.IsLocked,
Comments: issue.NumComments,
Created: issue.CreatedUnix.AsTime(),
Updated: issue.UpdatedUnix.AsTime(),
}

apiIssue.Repo = &api.RepositoryMeta{
Expand Down
17 changes: 9 additions & 8 deletions modules/convert/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import (
// ToComment converts a issues_model.Comment to the api.Comment format
func ToComment(c *issues_model.Comment) *api.Comment {
return &api.Comment{
ID: c.ID,
Poster: ToUser(c.Poster, nil),
HTMLURL: c.HTMLURL(),
IssueURL: c.IssueURL(),
PRURL: c.PRURL(),
Body: c.Content,
Created: c.CreatedUnix.AsTime(),
Updated: c.UpdatedUnix.AsTime(),
ID: c.ID,
Poster: ToUser(c.Poster, nil),
HTMLURL: c.HTMLURL(),
IssueURL: c.IssueURL(),
PRURL: c.PRURL(),
Body: c.Content,
Attachments: ToAttachments(c.Attachments),
Created: c.CreatedUnix.AsTime(),
Updated: c.UpdatedUnix.AsTime(),
}
}

Expand Down
19 changes: 1 addition & 18 deletions modules/convert/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import (

// ToRelease convert a repo_model.Release to api.Release
func ToRelease(r *repo_model.Release) *api.Release {
assets := make([]*api.Attachment, 0)
for _, att := range r.Attachments {
assets = append(assets, ToReleaseAttachment(att))
}
return &api.Release{
ID: r.ID,
TagName: r.TagName,
Expand All @@ -29,19 +25,6 @@ func ToRelease(r *repo_model.Release) *api.Release {
CreatedAt: r.CreatedUnix.AsTime(),
PublishedAt: r.CreatedUnix.AsTime(),
Publisher: ToUser(r.Publisher, nil),
Attachments: assets,
}
}

// ToReleaseAttachment converts models.Attachment to api.Attachment
func ToReleaseAttachment(a *repo_model.Attachment) *api.Attachment {
return &api.Attachment{
ID: a.ID,
Name: a.Name,
Created: a.CreatedUnix.AsTime(),
DownloadCount: a.DownloadCount,
Size: a.Size,
UUID: a.UUID,
DownloadURL: a.DownloadURL(),
Attachments: ToAttachments(r.Attachments),
}
}
5 changes: 5 additions & 0 deletions modules/notification/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ func (m *webhookNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues
}

func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) {
if err := issue.LoadRepo(ctx); err != nil {
log.Error("LoadRepo: %v", err)
return
}

mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo)
var err error
if issue.IsPull {
Expand Down
25 changes: 13 additions & 12 deletions modules/structs/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@ type RepositoryMeta struct {
// Issue represents an issue in a repository
// swagger:model
type Issue struct {
ID int64 `json:"id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Title string `json:"title"`
Body string `json:"body"`
Ref string `json:"ref"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
ID int64 `json:"id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Title string `json:"title"`
Body string `json:"body"`
Ref string `json:"ref"`
Attachments []*Attachment `json:"assets"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
// deprecated
Assignee *User `json:"assignee"`
Assignees []*User `json:"assignees"`
Expand Down
17 changes: 9 additions & 8 deletions modules/structs/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (

// Comment represents a comment on a commit or issue
type Comment struct {
ID int64 `json:"id"`
HTMLURL string `json:"html_url"`
PRURL string `json:"pull_request_url"`
IssueURL string `json:"issue_url"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Body string `json:"body"`
ID int64 `json:"id"`
HTMLURL string `json:"html_url"`
PRURL string `json:"pull_request_url"`
IssueURL string `json:"issue_url"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Body string `json:"body"`
Attachments []*Attachment `json:"assets"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
Expand Down
25 changes: 25 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,13 @@ func mustNotBeArchived(ctx *context.APIContext) {
}
}

func mustEnableAttachments(ctx *context.APIContext) {
if !setting.Attachment.Enabled {
ctx.NotFound()
return
}
}

// bind binding an obj to a func(ctx *context.APIContext)
func bind(obj interface{}) http.HandlerFunc {
tp := reflect.TypeOf(obj)
Expand Down Expand Up @@ -892,6 +899,15 @@ func Routes(ctx gocontext.Context) *web.Route {
Get(repo.GetIssueCommentReactions).
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
m.Group("/assets", func() {
m.Combo("").
Get(repo.ListIssueCommentAttachments).
Post(reqToken(), mustNotBeArchived, repo.CreateIssueCommentAttachment)
m.Combo("/{asset}").
Get(repo.GetIssueCommentAttachment).
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment).
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueCommentAttachment)
}, mustEnableAttachments)
})
})
m.Group("/{index}", func() {
Expand Down Expand Up @@ -935,6 +951,15 @@ func Routes(ctx gocontext.Context) *web.Route {
Get(repo.GetIssueReactions).
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueReaction).
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
m.Group("/assets", func() {
m.Combo("").
Get(repo.ListIssueAttachments).
Post(reqToken(), mustNotBeArchived, repo.CreateIssueAttachment)
m.Combo("/{asset}").
Get(repo.GetIssueAttachment).
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueAttachment)
}, mustEnableAttachments)
})
}, mustEnableIssuesOrPulls)
m.Group("/labels", func() {
Expand Down
Loading

0 comments on commit 3c59d31

Please sign in to comment.