From 8dca9f95fab909c52cd34fb401f171d22f0065ae Mon Sep 17 00:00:00 2001 From: Iwan Budi Kusnanto Date: Sat, 27 Aug 2016 01:23:21 +0700 Subject: [PATCH] issues comment API : list, create, edit (#2966) add `since` query string support to list issue comment --- models/issue_comment.go | 13 +++ routers/api/v1/api.go | 6 ++ routers/api/v1/repo/issue_comment.go | 122 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 routers/api/v1/repo/issue_comment.go diff --git a/models/issue_comment.go b/models/issue_comment.go index bd1a089ba62..8abc063328c 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -11,6 +11,7 @@ import ( "github.com/Unknwon/com" "github.com/go-xorm/xorm" + api "github.com/gogits/go-gogs-client" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/markdown" @@ -104,6 +105,18 @@ func (c *Comment) AfterDelete() { } } +// APIFormat convert Comment struct to api.Comment struct +func (c *Comment) APIFormat() *api.Comment { + apiComment := &api.Comment{ + ID: c.ID, + Poster: c.Poster.APIFormat(), + Body: c.Content, + Created: c.Created, + } + + return apiComment +} + // HashTag returns unique hash tag for comment. func (c *Comment) HashTag() string { return "issuecomment-" + com.ToStr(c.ID) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index ffbfce893aa..16322fbffd9 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -261,6 +261,12 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("").Get(repo.ListIssues).Post(bind(api.CreateIssueOption{}), repo.CreateIssue) m.Group("/:index", func() { m.Combo("").Get(repo.GetIssue).Patch(bind(api.EditIssueOption{}), repo.EditIssue) + + m.Group("/comments", func() { + m.Combo("").Get(repo.ListIssueComments).Post(bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment) + m.Combo("/:id").Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueComment) + }) + m.Group("/labels", func() { m.Combo("").Get(repo.ListIssueLabels). Post(bind(api.IssueLabelsOption{}), repo.AddIssueLabels). diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go new file mode 100644 index 00000000000..c3a80f989cb --- /dev/null +++ b/routers/api/v1/repo/issue_comment.go @@ -0,0 +1,122 @@ +// Copyright 2015 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +package repo + +import ( + "time" + + api "github.com/gogits/go-gogs-client" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/context" + "github.com/gogits/gogs/modules/log" +) + +const ( + ISO8601Format = "2006-01-02T15:04:05Z" +) + +// ListIssueComments list comments on an issue +func ListIssueComments(ctx *context.APIContext) { + var since time.Time + var withSince bool + + // we get the issue instead of comments directly + // because to get comments we need to gets issue first, + // and there is already comments in the issue + issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + if err != nil { + ctx.Error(500, "Comments", err) + return + } + + // parse `since`, by default we don't use `since` + if len(ctx.Query("since")) > 0 { + var err error + since, err = time.Parse(ISO8601Format, ctx.Query("since")) + if err == nil { + withSince = true + } + } + + apiComments := []*api.Comment{} + for _, comment := range issue.Comments { + if withSince && !comment.Created.After(since) { + continue + } + apiComments = append(apiComments, comment.APIFormat()) + } + + ctx.JSON(200, &apiComments) +} + +// CreateIssueComment create comment on an issue +func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOption) { + // check issue + issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + if err != nil { + ctx.Error(500, "Comments", err) + return + } + + comment := &models.Comment{ + Content: form.Body, + } + + if len(form.Body) == 0 { + ctx.Handle(400, "CreateIssueComment:empty content", err) + return + } + + // create comment + comment, err = models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, []string{}) + if err != nil { + ctx.Handle(500, "CreateIssueComment", err) + return + } + + log.Trace("Comment created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, comment.ID) + + // Refetch from database to assign some automatic values + comment, err = models.GetCommentByID(comment.ID) + if err != nil { + log.Info("Failed to refetch comment:%v", err) + } + ctx.JSON(201, comment.APIFormat()) +} + +// EditIssueComment edits an issue comment +func EditIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) { + comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) + if err != nil { + if models.IsErrCommentNotExist(err) { + ctx.Error(404, "GetCommentByID", err) + } else { + ctx.Handle(500, "GetCommentByID", err) + } + return + } + + if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { + ctx.Error(403, "edit comment", err) + return + } else if comment.Type != models.COMMENT_TYPE_COMMENT { + ctx.Error(204, "edit comment", err) + return + } + + comment.Content = form.Body + if len(comment.Content) == 0 { + ctx.JSON(200, map[string]interface{}{ + "content": "", + }) + return + } + + if err := models.UpdateComment(comment); err != nil { + ctx.Handle(500, "UpdateComment", err) + return + } + ctx.JSON(200, comment.APIFormat()) +}