diff --git a/models/issues/comment.go b/models/issues/comment.go index 10719101b6..4a819f51ae 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -1347,17 +1347,17 @@ func FixCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { return res.RowsAffected() } -func (c *Comment) GetIRI() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) GetIRI(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { return "" } if strings.Contains(c.Issue.Repo.OwnerName, "@") { return c.OldTitle } - return setting.AppURL + "api/v1/activitypub/note/" + c.Issue.Repo.OwnerName + "/" + c.Issue.Repo.Name + "/" + strconv.FormatInt(c.Issue.Index, 10) + "/" + strconv.FormatInt(c.ID, 10) + return setting.AppURL + "api/v1/activitypub/note/" + c.Issue.Repo.OwnerName + "/" + c.Issue.Repo.Name + "/" + strconv.FormatInt(c.ID, 10) } diff --git a/models/issues/issue.go b/models/issues/issue.go index c120176783..e379554d26 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -2398,8 +2398,8 @@ func DeleteOrphanedIssues(ctx context.Context) error { return nil } -func (issue *Issue) GetIRI() string { - err := issue.LoadRepo(db.DefaultContext) +func (issue *Issue) GetIRI(ctx context.Context) string { + err := issue.LoadRepo(ctx) if err != nil { log.Error(fmt.Sprintf("loadRepo: %v", err)) } diff --git a/routers/api/v1/activitypub/note.go b/routers/api/v1/activitypub/note.go index 8e86e4a7cd..e06f8bc6f6 100644 --- a/routers/api/v1/activitypub/note.go +++ b/routers/api/v1/activitypub/note.go @@ -4,7 +4,7 @@ package activitypub import ( - "strconv" + "net/http" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" @@ -13,7 +13,7 @@ import ( // Note function returns the Note object for a comment to an issue or PR func Note(ctx *context.APIContext) { - // swagger:operation GET /activitypub/note/{username}/{reponame}/{id}/{noteid} activitypub activitypubNote + // swagger:operation GET /activitypub/note/{username}/{reponame}/{noteid} activitypub activitypubNote // --- // summary: Returns the Note object for a comment to an issue or PR // produces: @@ -29,11 +29,6 @@ func Note(ctx *context.APIContext) { // description: name of the repo // type: string // required: true - // - name: id - // in: path - // description: ID number of the issue or PR - // type: string - // required: true // - name: noteid // in: path // description: ID number of the comment @@ -42,19 +37,34 @@ func Note(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityPub" + // "204": + // "$ref": "#/responses/empty" + // "404": + // "$ref": "#/responses/notFound" - index, err := strconv.ParseInt(ctx.Params("noteid"), 10, 64) + comment, err := issues_model.GetCommentByID(ctx, ctx.ParamsInt64("noteid")) if err != nil { - ctx.ServerError("ParseInt", err) + if issues_model.IsErrCommentNotExist(err) { + ctx.NotFound(err) + } else { + ctx.Error(http.StatusInternalServerError, "GetCommentByID", err) + } return } - // TODO: index can be spoofed!!! - comment, err := issues_model.GetCommentByID(ctx, index) - if err != nil { - ctx.ServerError("GetCommentByID", err) + + // Ensure the comment comes from the specified repository. + if comment.Issue.RepoID != ctx.Repo.Repository.ID { + ctx.Status(http.StatusNotFound) return } - note, err := activitypub.Note(comment) + + // Only allow comments and not events. + if comment.Type != issues_model.CommentTypeComment { + ctx.Status(http.StatusNoContent) + return + } + + note, err := activitypub.Note(ctx, comment) if err != nil { ctx.ServerError("Note", err) return diff --git a/routers/api/v1/activitypub/ticket.go b/routers/api/v1/activitypub/ticket.go index 8f2cfc6e6f..ab0fe4fc7b 100644 --- a/routers/api/v1/activitypub/ticket.go +++ b/routers/api/v1/activitypub/ticket.go @@ -4,8 +4,6 @@ package activitypub import ( - "strconv" - issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/services/activitypub" @@ -37,18 +35,20 @@ func Ticket(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityPub" + // "404": + // "$ref": "#/responses/notFound" - index, err := strconv.ParseInt(ctx.Params("id"), 10, 64) + issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64("id")) if err != nil { - ctx.ServerError("ParseInt", err) + if issues_model.IsErrIssueNotExist(err) { + ctx.NotFound() + } else { + ctx.ServerError("GetIssueByIndex", err) + } return } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, index) - if err != nil { - ctx.ServerError("GetIssueByIndex", err) - return - } - ticket, err := activitypub.Ticket(issue) + + ticket, err := activitypub.Ticket(ctx, issue) if err != nil { ctx.ServerError("Ticket", err) return diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 4e148bdc76..2ed0fd5dea 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -657,7 +657,7 @@ func Routes(ctx gocontext.Context) *web.Route { m.Get("/followers", activitypub.RepoFollowers) }, repoAssignment()) m.Get("/ticket/{username}/{reponame}/{id}", repoAssignment(), activitypub.Ticket) - m.Get("/note/{username}/{reponame}/{id}/{noteid}", repoAssignment(), activitypub.Note) + m.Get("/note/{username}/{reponame}/{noteid}", repoAssignment(), activitypub.Note) }) } m.Get("/signing-key.gpg", misc.SigningKey) diff --git a/services/activitypub/objects.go b/services/activitypub/objects.go index 8a1ec9f1cf..bbd11e6885 100644 --- a/services/activitypub/objects.go +++ b/services/activitypub/objects.go @@ -4,9 +4,9 @@ package activitypub import ( + "context" "strconv" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/forgefed" @@ -14,20 +14,20 @@ import ( ) // Construct a Note object from a comment -func Note(comment *issues_model.Comment) (*ap.Note, error) { - err := comment.LoadPoster(db.DefaultContext) +func Note(ctx context.Context, comment *issues_model.Comment) (*ap.Note, error) { + err := comment.LoadPoster(ctx) if err != nil { return nil, err } - err = comment.LoadIssue(db.DefaultContext) + err = comment.LoadIssue(ctx) if err != nil { return nil, err } note := ap.Note{ Type: ap.NoteType, - ID: ap.IRI(comment.GetIRI()), + ID: ap.IRI(comment.GetIRI(ctx)), AttributedTo: ap.IRI(comment.Poster.GetIRI()), - Context: ap.IRI(comment.Issue.GetIRI()), + Context: ap.IRI(comment.Issue.GetIRI(ctx)), To: ap.ItemCollection{ap.IRI("https://www.w3.org/ns/activitystreams#Public")}, } note.Content = ap.NaturalLanguageValuesNew() @@ -39,8 +39,8 @@ func Note(comment *issues_model.Comment) (*ap.Note, error) { } // Construct a Ticket object from an issue -func Ticket(issue *issues_model.Issue) (*forgefed.Ticket, error) { - iri := issue.GetIRI() +func Ticket(ctx context.Context, issue *issues_model.Issue) (*forgefed.Ticket, error) { + iri := issue.GetIRI(ctx) ticket := forgefed.TicketNew() ticket.Type = forgefed.TicketType ticket.ID = ap.IRI(iri) @@ -53,13 +53,13 @@ func Ticket(issue *issues_model.Issue) (*forgefed.Ticket, error) { return nil, err } - err = issue.LoadRepo(db.DefaultContext) + err = issue.LoadRepo(ctx) if err != nil { return nil, err } ticket.Context = ap.IRI(issue.Repo.GetIRI()) - err = issue.LoadPoster(db.DefaultContext) + err = issue.LoadPoster(ctx) if err != nil { return nil, err } diff --git a/services/issue/comments.go b/services/issue/comments.go index 4ad064a3f8..19abbdda7c 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -82,7 +82,7 @@ func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_m if strings.Contains(repo.OwnerName, "@") { // Federated comment - note, err := activitypub.Note(comment) + note, err := activitypub.Note(ctx, comment) if err != nil { return nil, err } diff --git a/services/issue/issue.go b/services/issue/issue.go index d097b60d68..31fc7631d2 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -29,7 +29,7 @@ func NewIssue(repo *repo_model.Repository, issue *issues_model.Issue, labelIDs [ if strings.Contains(repo.OwnerName, "@") { // Federated issue - ticket, err := activitypub.Ticket(issue) + ticket, err := activitypub.Ticket(db.DefaultContext, issue) if err != nil { return err } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4f034e22a3..0bb066645b 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -23,7 +23,7 @@ }, "basePath": "{{AppSubUrl | JSEscape | Safe}}/api/v1", "paths": { - "/activitypub/note/{username}/{reponame}/{id}/{noteid}": { + "/activitypub/note/{username}/{reponame}/{noteid}": { "get": { "produces": [ "application/activity+json" @@ -48,13 +48,6 @@ "in": "path", "required": true }, - { - "type": "string", - "description": "ID number of the issue or PR", - "name": "id", - "in": "path", - "required": true - }, { "type": "string", "description": "ID number of the comment", @@ -66,6 +59,12 @@ "responses": { "200": { "$ref": "#/responses/ActivityPub" + }, + "204": { + "$ref": "#/responses/empty" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -238,6 +237,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityPub" + }, + "404": { + "$ref": "#/responses/notFound" } } }