add detection of reply and disable edit for such comments #248

This commit is contained in:
Umputun
2019-01-15 17:05:30 -06:00
parent 367c3d0cc2
commit dff266ec01
2 changed files with 82 additions and 1 deletions
+25
View File
@@ -49,6 +49,7 @@ type PostMetaData struct {
}
const defaultCommentMaxSize = 2000
const maxLastCommentsReply = 1000
// UnlimitedVotes doesn't restrict MaxVotes
const UnlimitedVotes = -1
@@ -179,6 +180,10 @@ func (s *DataStore) EditComment(locator store.Locator, commentID string, req Edi
return comment, errors.Errorf("too late to edit %s", commentID)
}
if s.HasReplies(comment) {
return comment, errors.Errorf("parent comment with reply can't be edited, %s", commentID)
}
if req.Delete { // delete request
comment.Deleted = true
return comment, s.Delete(locator, commentID, store.SoftDelete)
@@ -196,6 +201,26 @@ func (s *DataStore) EditComment(locator store.Locator, commentID string, req Edi
return comment, err
}
// HasReplies checks if there is any reply to the comments
// Loads last maxLastCommentsReply comments and compare parent id to the comment's id
// TODO: add caching?
func (s *DataStore) HasReplies(comment store.Comment) bool {
comments, err := s.Last(comment.Locator.SiteID, maxLastCommentsReply)
if err != nil {
log.Printf("[WARN] can't get last comments for reply check, %v", err)
return false
}
for _, c := range comments {
if c.ParentID != "" && !c.Deleted && c.User.ID != comment.User.ID { // not interested in replies to yourself and top level
if c.ParentID == comment.ID {
return true
}
}
}
return false
}
// SetTitle puts title from the locator.URL page and overwrites any existing title
func (s *DataStore) SetTitle(locator store.Locator, commentID string) (comment store.Comment, err error) {
if s.TitleExtractor == nil {
+57 -1
View File
@@ -12,7 +12,7 @@ import (
"testing"
"time"
"github.com/coreos/bbolt"
bolt "github.com/coreos/bbolt"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -404,6 +404,32 @@ func TestService_EditCommentDurationFailed(t *testing.T) {
assert.NotNil(t, err)
}
func TestService_EditCommentReplyFailed(t *testing.T) {
defer os.Remove(testDb)
b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")}
res, err := b.Last("radio-t", 0)
t.Logf("%+v", res[1])
assert.Nil(t, err)
assert.Equal(t, 2, len(res))
assert.Nil(t, res[1].Edit)
reply := store.Comment{
ID: "123456",
ParentID: "id-1",
Text: "some text",
Timestamp: time.Date(2017, 12, 20, 15, 18, 22, 0, time.Local),
Locator: store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"},
User: store.User{ID: "user2", Name: "user name 2"},
}
_, err = b.Create(reply)
assert.NoError(t, err)
_, err = b.EditComment(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[1].ID,
EditRequest{Orig: "yyy", Text: "xxx", Summary: "my edit"})
assert.EqualError(t, err, "parent comment with reply can't be edited, id-1")
}
func TestService_ValidateComment(t *testing.T) {
b := DataStore{MaxCommentSize: 2000, AdminStore: admin.NewStaticKeyStore("secret 123")}
@@ -523,6 +549,36 @@ func TestService_IsAdmin(t *testing.T) {
assert.True(t, b.IsAdmin("radio-t", "user2"))
}
func TestService_HasReplies(t *testing.T) {
defer os.Remove(testDb)
// two comments for https://radio-t.com, no reply
b := DataStore{Interface: prepStoreEngine(t), EditDuration: 100 * time.Millisecond,
AdminStore: admin.NewStaticStore("secret 123", []string{"user2"}, "user@email.com")}
comment := store.Comment{
ID: "id-1",
Text: `some text, <a href="http://radio-t.com">link</a>`,
Timestamp: time.Date(2017, 12, 20, 15, 18, 22, 0, time.Local),
Locator: store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"},
User: store.User{ID: "user1", Name: "user name"},
}
assert.False(t, b.HasReplies(comment))
reply := store.Comment{
ID: "123456",
ParentID: "id-1",
Text: "some text",
Timestamp: time.Date(2017, 12, 20, 15, 18, 22, 0, time.Local),
Locator: store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"},
User: store.User{ID: "user2", Name: "user name 2"},
}
_, err := b.Create(reply)
assert.NoError(t, err)
assert.True(t, b.HasReplies(comment))
}
// makes new boltdb, put two records
func prepStoreEngine(t *testing.T) engine.Interface {
os.Remove(testDb)