diff --git a/README.md b/README.md index a84b3c48..004f68c4 100644 --- a/README.md +++ b/README.md @@ -485,15 +485,14 @@ type Node struct { Sort can be `time`, `active` or `score`. Supported sort order with prefix -/+, i.e. `-time`. For `tree` mode sort will be applied to top-level comments only and all replies always sorted by time. -* `PUT /api/v1/comment/{id}?site=site-id&url=post-url` - edit comment, allowed once in 5min since creation +* `PUT /api/v1/comment/{id}?site=site-id&url=post-url` - edit comment, allowed once in `EDIT_TIME` minutes since creation. Body is `EditRequest` json -```json - Content-Type: application/json - - { - "text": "edit comment blah http://radio-t.com 12345", - "summary": "fix blah" - } +```go + type EditRequest struct { + Text string `json:"text"` // updated text + Summary string `json:"summary"` // optional, summary of the edit + Delete bool `json:"delete"` // delete flag + }{} ``` * `GET /api/v1/last/{max}?site=site-id` - get up to `{max}` last comments diff --git a/backend/app/rest/api/rest_private.go b/backend/app/rest/api/rest_private.go index 1a47a895..5c147747 100644 --- a/backend/app/rest/api/rest_private.go +++ b/backend/app/rest/api/rest_private.go @@ -83,6 +83,7 @@ func (s *Rest) updateCommentCtrl(w http.ResponseWriter, r *http.Request) { edit := struct { Text string Summary string + Delete bool }{} if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &edit); err != nil { @@ -112,6 +113,7 @@ func (s *Rest) updateCommentCtrl(w http.ResponseWriter, r *http.Request) { Text: s.CommentFormatter.FormatText(edit.Text), Orig: edit.Text, Summary: edit.Summary, + Delete: edit.Delete, } res, err := s.DataService.EditComment(locator, id, editReq) diff --git a/backend/app/rest/api/rest_private_test.go b/backend/app/rest/api/rest_private_test.go index 7b775ad8..1dd820a9 100644 --- a/backend/app/rest/api/rest_private_test.go +++ b/backend/app/rest/api/rest_private_test.go @@ -186,6 +186,45 @@ func TestRest_Update(t *testing.T) { assert.Equal(t, c2, c3, "same as response from update") } +func TestRest_UpdateDelete(t *testing.T) { + srv, ts := prep(t) + assert.NotNil(t, srv) + defer cleanup(ts, srv) + + c1 := store.Comment{Text: "test test #1", ParentID: "p1", + Locator: store.Locator{SiteID: "radio-t", URL: "https://radio-t.com/blah1"}} + id := addComment(t, c1, ts) + + client := http.Client{} + req, err := http.NewRequest(http.MethodPut, ts.URL+"/api/v1/comment/"+id+"?site=radio-t&url=https://radio-t.com/blah1", + strings.NewReader(`{"delete": true, "summary":"removed by user"}`)) + assert.Nil(t, err) + req.SetBasicAuth("dev", "password") + b, err := client.Do(req) + assert.Nil(t, err) + body, err := ioutil.ReadAll(b.Body) + assert.Nil(t, err) + assert.Equal(t, 200, b.StatusCode, string(body)) + + // comments returned by update + c2 := store.Comment{} + err = json.Unmarshal(body, &c2) + assert.Nil(t, err) + assert.Equal(t, id, c2.ID) + assert.True(t, c2.Deleted) + + // read updated comment + res, code := getWithAuth(t, fmt.Sprintf("%s/api/v1/id/%s?site=radio-t&url=https://radio-t.com/blah1", ts.URL, id)) + assert.Equal(t, 200, code) + c3 := store.Comment{} + err = json.Unmarshal([]byte(res), &c3) + assert.Nil(t, err) + assert.Equal(t, "", c3.Text) + assert.Equal(t, "", c3.Orig) + assert.True(t, c3.Deleted) + +} + func TestRest_UpdateNotOwner(t *testing.T) { srv, ts := prep(t) assert.NotNil(t, srv) diff --git a/backend/app/store/service/service.go b/backend/app/store/service/service.go index c9f2d852..8283d5b1 100644 --- a/backend/app/store/service/service.go +++ b/backend/app/store/service/service.go @@ -124,6 +124,7 @@ type EditRequest struct { Text string Orig string Summary string + Delete bool } // EditComment to edit text and update Edit info @@ -138,6 +139,11 @@ func (s *DataStore) EditComment(locator store.Locator, commentID string, req Edi return comment, errors.Errorf("too late to edit %s", commentID) } + if req.Delete { // delete request + comment.Deleted = true + return comment, s.Delete(locator, commentID, store.SoftDelete) + } + comment.Text = req.Text comment.Orig = req.Orig comment.Edit = &store.Edit{ diff --git a/backend/app/store/service/service_test.go b/backend/app/store/service/service_test.go index 590a65ba..645738ca 100644 --- a/backend/app/store/service/service_test.go +++ b/backend/app/store/service/service_test.go @@ -258,6 +258,25 @@ func TestService_EditComment(t *testing.T) { assert.Nil(t, err, "allow second edit") } +func TestService_DeleteComment(t *testing.T) { + defer os.Remove(testDb) + b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + + res, err := b.Last("radio-t", 0) + t.Logf("%+v", res[0]) + assert.Nil(t, err) + assert.Equal(t, 2, len(res)) + assert.Nil(t, res[0].Edit) + + _, err = b.EditComment(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, EditRequest{Delete: true}) + assert.Nil(t, err) + + c, err := b.Get(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID) + assert.Nil(t, err) + assert.True(t, c.Deleted) + t.Logf("%+v", c) +} + func TestService_EditCommentDurationFailed(t *testing.T) { defer os.Remove(testDb) b := DataStore{Interface: prepStoreEngine(t), EditDuration: 100 * time.Millisecond, KeyStore: keys.NewStaticStore("secret 123")}