diff --git a/app/store/engine/bolt_accessor.go b/app/store/engine/bolt_accessor.go index eebdb787..a7c4ea0d 100644 --- a/app/store/engine/bolt_accessor.go +++ b/app/store/engine/bolt_accessor.go @@ -407,7 +407,7 @@ func (b *BoltDB) save(bkt *bolt.Bucket, key []byte, comment store.Comment) (err func (b *BoltDB) load(bkt *bolt.Bucket, key []byte) (comment store.Comment, err error) { commentVal := bkt.Get(key) if commentVal == nil { - return comment, errors.Errorf("no comment for %s", key) + return comment, errors.Errorf("no comments for %s", key) } if err = json.Unmarshal(commentVal, &comment); err != nil { diff --git a/app/store/engine/bolt_test.go b/app/store/engine/bolt_accessor_test.go similarity index 66% rename from app/store/engine/bolt_test.go rename to app/store/engine/bolt_accessor_test.go index ab3cdbc3..c1d38b2e 100644 --- a/app/store/engine/bolt_test.go +++ b/app/store/engine/bolt_accessor_test.go @@ -32,84 +32,6 @@ func TestBoltDB_CreateAndFind(t *testing.T) { assert.EqualError(t, err, `site "radio-t-bad" not found`) } -func TestBoltDB_Delete(t *testing.T) { - defer os.Remove(testDb) - b := prep(t) - - loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} - res, err := b.Find(loc, "time") - assert.Nil(t, err) - assert.Equal(t, 2, len(res), "initially 2 comments") - - err = b.Delete(loc, res[0].ID, store.SoftDelete) - assert.Nil(t, err) - - res, err = b.Find(loc, "time") - assert.Nil(t, err) - assert.Equal(t, 2, len(res)) - assert.Equal(t, "", res[0].Text) - assert.True(t, res[0].Deleted, "marked deleted") - assert.Equal(t, store.User{Name: "user name", ID: "user1", Picture: "", Admin: false, Blocked: false, IP: ""}, res[0].User) - - assert.Equal(t, "some text2", res[1].Text) - assert.False(t, res[1].Deleted) - - comments, err := b.Last("radio-t", 10) - assert.Nil(t, err) - assert.Equal(t, 1, len(comments), "1 in last, 1 removed") - - err = b.Delete(loc, "123456", store.SoftDelete) - assert.NotNil(t, err) - - loc.SiteID = "bad" - err = b.Delete(loc, res[0].ID, store.SoftDelete) - assert.EqualError(t, err, `site "bad" not found`) -} - -func TestBoltDB_DeleteHard(t *testing.T) { - defer os.Remove(testDb) - b := prep(t) - - loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} - res, err := b.Find(loc, "time") - assert.Nil(t, err) - assert.Equal(t, 2, len(res), "initially 2 comments") - - err = b.Delete(loc, res[0].ID, store.HardDelete) - assert.Nil(t, err) - - res, err = b.Find(loc, "time") - assert.Nil(t, err) - assert.Equal(t, 2, len(res)) - assert.Equal(t, "", res[0].Text) - assert.True(t, res[0].Deleted, "marked deleted") - assert.Equal(t, store.User{Name: "deleted", ID: "deleted", Picture: "", Admin: false, Blocked: false, IP: ""}, res[0].User) -} - -func TestBoltDB_DeleteAll(t *testing.T) { - defer os.Remove(testDb) - b := prep(t) - - loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} - res, err := b.Find(loc, "time") - assert.Nil(t, err) - assert.Equal(t, 2, len(res), "initially 2 comments") - - err = b.DeleteAll("radio-t") - assert.Nil(t, err) - - comments, err := b.Last("radio-t", 10) - assert.Nil(t, err) - assert.Equal(t, 0, len(comments), "nothing left") - - c, err := b.Count(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}) - assert.Nil(t, err) - assert.Equal(t, 0, c, "0 count") - - err = b.DeleteAll("bad") - assert.EqualError(t, err, `site "bad" not found`) -} - func TestBoltDB_Get(t *testing.T) { defer os.Remove(testDb) b := prep(t) @@ -187,44 +109,6 @@ func TestBoltDB_Count(t *testing.T) { assert.EqualError(t, err, `site "bad" not found`) } -func TestBoltDB_BlockUser(t *testing.T) { - defer os.Remove(testDb) - b := prep(t) - - assert.False(t, b.IsBlocked("radio-t", "user1"), "nothing blocked") - - assert.NoError(t, b.SetBlock("radio-t", "user1", true)) - assert.True(t, b.IsBlocked("radio-t", "user1"), "user1 blocked") - - assert.False(t, b.IsBlocked("radio-t", "user2"), "user2 still unblocked") - - assert.NoError(t, b.SetBlock("radio-t", "user1", false)) - assert.False(t, b.IsBlocked("radio-t", "user1"), "user1 unblocked") - - assert.EqualError(t, b.SetBlock("bad", "user1", true), `site "bad" not found`) - assert.NoError(t, b.SetBlock("radio-t", "userX", false)) -} - -func TestBoltDB_BlockList(t *testing.T) { - defer os.Remove(testDb) - b := prep(t) - - assert.NoError(t, b.SetBlock("radio-t", "user1", true)) - assert.NoError(t, b.SetBlock("radio-t", "user2", true)) - assert.NoError(t, b.SetBlock("radio-t", "user3", false)) - - ids, err := b.Blocked("radio-t") - assert.NoError(t, err) - - assert.Equal(t, 2, len(ids)) - assert.Equal(t, "user1", ids[0].ID) - assert.Equal(t, "user2", ids[1].ID) - t.Logf("%+v", ids) - - _, err = b.Blocked("bad") - assert.EqualError(t, err, `site "bad" not found`) -} - func TestBoltDB_List(t *testing.T) { defer os.Remove(testDb) b := prep(t) // two comments for https://radio-t.com diff --git a/app/store/engine/bolt_admin.go b/app/store/engine/bolt_admin.go index e233168a..946cc0f2 100644 --- a/app/store/engine/bolt_admin.go +++ b/app/store/engine/bolt_admin.go @@ -1,6 +1,8 @@ package engine import ( + "encoding/json" + "log" "time" "github.com/coreos/bbolt" @@ -105,10 +107,10 @@ func (b *BoltDB) DeleteUser(siteID string, userID string) error { postsBkt := tx.Bucket([]byte(postsBucketName)) for _, postInfo := range posts { postBkt := postsBkt.Bucket([]byte(postInfo.URL)) - err = postsBkt.ForEach(func(k []byte, v []byte) error { - comment, e := b.load(postBkt, k) - if e != nil { - return errors.Wrapf(e, "can't load key %s from bucket %s", k, postInfo.URL) + err = postBkt.ForEach(func(postURL []byte, commentVal []byte) error { + comment := store.Comment{} + if err = json.Unmarshal(commentVal, &comment); err != nil { + return errors.Wrap(err, "failed to unmarshal") } if comment.User.ID == userID { comments = append(comments, commentInfo{locator: comment.Locator, commentID: comment.ID}) @@ -125,7 +127,7 @@ func (b *BoltDB) DeleteUser(siteID string, userID string) error { if err != nil { return errors.Wrapf(err, "failed to collect list of all comments for deletion") } - + log.Printf("[DEBUG] comments for removal=%d", len(comments)) // delete collected comments for _, ci := range comments { if e := b.Delete(ci.locator, ci.commentID, store.HardDelete); e != nil { diff --git a/app/store/engine/bolt_admin_test.go b/app/store/engine/bolt_admin_test.go new file mode 100644 index 00000000..dac4955b --- /dev/null +++ b/app/store/engine/bolt_admin_test.go @@ -0,0 +1,153 @@ +package engine + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + + "github.com/umputun/remark/app/store" +) + +func TestBoltDB_Delete(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + + loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} + res, err := b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res), "initially 2 comments") + + err = b.Delete(loc, res[0].ID, store.SoftDelete) + assert.Nil(t, err) + + res, err = b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res)) + assert.Equal(t, "", res[0].Text) + assert.True(t, res[0].Deleted, "marked deleted") + assert.Equal(t, store.User{Name: "user name", ID: "user1", Picture: "", Admin: false, Blocked: false, IP: ""}, res[0].User) + + assert.Equal(t, "some text2", res[1].Text) + assert.False(t, res[1].Deleted) + + comments, err := b.Last("radio-t", 10) + assert.Nil(t, err) + assert.Equal(t, 1, len(comments), "1 in last, 1 removed") + + err = b.Delete(loc, "123456", store.SoftDelete) + assert.NotNil(t, err) + + loc.SiteID = "bad" + err = b.Delete(loc, res[0].ID, store.SoftDelete) + assert.EqualError(t, err, `site "bad" not found`) +} + +func TestBoltDB_DeleteHard(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + + loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} + res, err := b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res), "initially 2 comments") + + err = b.Delete(loc, res[0].ID, store.HardDelete) + assert.Nil(t, err) + + res, err = b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res)) + assert.Equal(t, "", res[0].Text) + assert.True(t, res[0].Deleted, "marked deleted") + assert.Equal(t, store.User{Name: "deleted", ID: "deleted", Picture: "", Admin: false, Blocked: false, IP: ""}, res[0].User) +} + +func TestBoltDB_DeleteAll(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + + loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} + res, err := b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res), "initially 2 comments") + + err = b.DeleteAll("radio-t") + assert.Nil(t, err) + + comments, err := b.Last("radio-t", 10) + assert.Nil(t, err) + assert.Equal(t, 0, len(comments), "nothing left") + + c, err := b.Count(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}) + assert.Nil(t, err) + assert.Equal(t, 0, c, "0 count") + + err = b.DeleteAll("bad") + assert.EqualError(t, err, `site "bad" not found`) +} + +func TestBoltDB_DeleteUser(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + err := b.DeleteUser("radio-t", "user1") + require.NoError(t, err) + + loc := store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"} + res, err := b.Find(loc, "time") + assert.Nil(t, err) + assert.Equal(t, 2, len(res), "2 comments with deleted info") + assert.Equal(t, store.User{Name: "deleted", ID: "deleted", Picture: "", Admin: false, Blocked: false, IP: ""}, res[0].User) + assert.Equal(t, store.User{Name: "deleted", ID: "deleted", Picture: "", Admin: false, Blocked: false, IP: ""}, res[1].User) + + c, err := b.Count(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}) + assert.Nil(t, err) + assert.Equal(t, 0, c, "0 count") + + _, _, err = b.User("radio-t", "user1", 5) + assert.EqualError(t, err, "no comments for user user1 in store") + + comments, err := b.Last("radio-t", 10) + assert.Nil(t, err) + assert.Equal(t, 0, len(comments), "nothing left") +} + +func TestBoltDB_BlockUser(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + + assert.False(t, b.IsBlocked("radio-t", "user1"), "nothing blocked") + + assert.NoError(t, b.SetBlock("radio-t", "user1", true)) + assert.True(t, b.IsBlocked("radio-t", "user1"), "user1 blocked") + + assert.False(t, b.IsBlocked("radio-t", "user2"), "user2 still unblocked") + + assert.NoError(t, b.SetBlock("radio-t", "user1", false)) + assert.False(t, b.IsBlocked("radio-t", "user1"), "user1 unblocked") + + assert.EqualError(t, b.SetBlock("bad", "user1", true), `site "bad" not found`) + assert.NoError(t, b.SetBlock("radio-t", "userX", false)) +} + +func TestBoltDB_BlockList(t *testing.T) { + defer os.Remove(testDb) + b := prep(t) + + assert.NoError(t, b.SetBlock("radio-t", "user1", true)) + assert.NoError(t, b.SetBlock("radio-t", "user2", true)) + assert.NoError(t, b.SetBlock("radio-t", "user3", false)) + + ids, err := b.Blocked("radio-t") + assert.NoError(t, err) + + assert.Equal(t, 2, len(ids)) + assert.Equal(t, "user1", ids[0].ID) + assert.Equal(t, "user2", ids[1].ID) + t.Logf("%+v", ids) + + _, err = b.Blocked("bad") + assert.EqualError(t, err, `site "bad" not found`) +}