add comment update (edit once)

This commit is contained in:
Umputun
2018-01-03 13:34:18 -06:00
parent e949927df6
commit acfce21724
6 changed files with 110 additions and 3 deletions
+45
View File
@@ -89,6 +89,7 @@ func (s *Server) Run() {
// protected routes, require auth
rapi.With(auth.Auth(s.SessionStore, s.Admins, maybeDevMode(auth.Full))).Group(func(rauth chi.Router) {
rauth.Post("/comment", s.createCommentCtrl)
rauth.Put("/comment/{id}", s.updateCommentCtrl)
rauth.Get("/user", s.userInfoCtrl)
rauth.Put("/vote/{id}", s.voteCtrl)
@@ -148,6 +149,50 @@ func (s *Server) createCommentCtrl(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, JSON{"id": id, "loc": comment.Locator})
}
// PUT /comment/{id}?site=siteID&url=post-url - update comment
func (s *Server) updateCommentCtrl(w http.ResponseWriter, r *http.Request) {
edit := struct {
Text string
Summary string
}{}
if err := render.DecodeJSON(r.Body, &edit); err != nil {
common.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment")
return
}
user, err := common.GetUserInfo(r)
if err != nil { // this not suppose to happen (handled by Auth), just dbl-check
common.SendErrorJSON(w, r, http.StatusUnauthorized, err, "can't get user info")
return
}
locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")}
id := chi.URLParam(r, "id")
log.Printf("[DEBUG] update comment %s, %+v", id, edit)
var currComment store.Comment
if currComment, err = s.DataService.Get(locator, id); err != nil {
common.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't find comment")
return
}
if currComment.User.ID != user.ID {
common.SendErrorJSON(w, r, http.StatusForbidden, errors.New("rejected"), "can not edit comments for other users")
return
}
res, err := s.DataService.EditComment(locator, id, edit.Text, store.Edit{Summary: edit.Summary})
if err != nil {
common.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't update comment")
return
}
s.respCache.Flush() // reset all caches
render.JSON(w, r, JSON{"id": id, "loc": locator, "comment": res})
}
// DELETE /comment/{id}?site=siteID&url=post-url
func (s *Server) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) {
+1 -2
View File
@@ -11,9 +11,8 @@ import (
var testDb = "/tmp/test-remark.db"
func TestBoltDB_CreateAndFind(t *testing.T) {
var b Interface
var b Interface = prep(t)
defer os.Remove(testDb)
b = prep(t)
res, err := b.Find(Request{Locator: Locator{URL: "https://radio-t.com", SiteID: "radio-t"}})
assert.Nil(t, err)
+24 -1
View File
@@ -1,6 +1,10 @@
package store
import "github.com/pkg/errors"
import (
"time"
"github.com/pkg/errors"
)
// Service wraps store.Interface with additional methods
type Service struct {
@@ -39,3 +43,22 @@ func (s *Service) Vote(locator Locator, commentID string, userID string, val boo
return comment, s.Put(locator, comment)
}
// EditComment to edit text and update Edit info
func (s *Service) EditComment(locator Locator, commentID string, text string, edit Edit) (comment Comment, err error) {
comment, err = s.Get(locator, commentID)
if err != nil {
return comment, err
}
// edit allowed only once
if !comment.Edit.Timestamp.IsZero() {
return comment, errors.Errorf("comment %s already edited at %s", commentID, comment.Edit.Timestamp)
}
comment.Text = text
comment.Edit = edit
comment.Edit.Timestamp = time.Now()
comment = sanitizeComment(comment)
err = s.Put(locator, comment)
return comment, err
}
+21
View File
@@ -55,3 +55,24 @@ func TestBoltDB_Pin(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, false, c.Pin)
}
func TestBoltDB_EditComment(t *testing.T) {
defer os.Remove(testDb)
b := Service{Interface: prep(t)}
res, err := b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 0)
t.Logf("%+v", res[0])
assert.Nil(t, err)
assert.Equal(t, 2, len(res))
assert.Equal(t, Edit{}, res[0].Edit)
comment, err := b.EditComment(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, "xxx", Edit{Summary: "my edit"})
assert.Nil(t, err)
assert.Equal(t, "my edit", comment.Edit.Summary)
assert.Equal(t, "xxx", comment.Text)
c, err := b.GetByID(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID)
assert.Nil(t, err)
assert.Equal(t, "my edit", c.Edit.Summary)
assert.Equal(t, "xxx", c.Text)
}
+7
View File
@@ -25,6 +25,7 @@ type Comment struct {
Votes map[string]bool `json:"votes"`
Timestamp time.Time `json:"time"`
Pin bool `json:"pin,omitempty"`
Edit Edit `json:"edit,omitempty"`
}
// Locator keeps site and url of the post
@@ -44,6 +45,12 @@ type User struct {
IP string `json:"-"`
}
// Edit indication
type Edit struct {
Timestamp time.Time `json:"time"`
Summary string `json:"summary"`
}
// Request is a container for all finds
type Request struct {
Locator Locator `json:"locator"`
+12
View File
@@ -25,6 +25,15 @@ Content-Type: application/json
}
}
### update comment
POST https://demo.remark42.com/api/v1/comment/a2ddb8d2f65008ee1a1e3af8df0f26beb042309c?site=remark&url=https://radio-t.com/blah1
Content-Type: application/json
{
"text": "edit comment blah http://radio-t.com 12345",
"summary": "fix blah"
}
### pin comment
PUT https://demo.remark42.com/api/v1/admin/pin/3665976683?site=remark&url=https://radio-t.com/p/2017/12/16/podcast-576/&pin=1
@@ -37,6 +46,9 @@ GET https://demo.remark42.com/api/v1/user
### get comment by id
GET https://demo.remark42.com/api/v1/id/3665976683?site=remark&url=https://radio-t.com/p/2017/12/16/podcast-576/
### get comment by id 2
GET https://demo.remark42.com/api/v1/id/a2ddb8d2f65008ee1a1e3af8df0f26beb042309c?site=remark&url=https://radio-t.com/blah1
### get comment by user id
GET https://demo.remark42.com/api/v1/comments?site=remark&user=umputun