1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-09 09:35:03 +09:00

Prevent deletion for derived

This commit is contained in:
mcrakhman 2023-09-26 22:35:47 +02:00
parent 3608a6949f
commit 61bd9aae1e
No known key found for this signature in database
GPG key ID: DED12CFEF5B8396B
6 changed files with 91 additions and 18 deletions

View file

@ -31,10 +31,11 @@ type SettingsObject interface {
}
var (
ErrDeleteSelf = errors.New("cannot delete self")
ErrAlreadyDeleted = errors.New("the object is already deleted")
ErrObjDoesNotExist = errors.New("the object does not exist")
ErrCantDeleteSpace = errors.New("not able to delete space")
ErrDeleteSelf = errors.New("cannot delete self")
ErrAlreadyDeleted = errors.New("the object is already deleted")
ErrObjDoesNotExist = errors.New("the object does not exist")
ErrCantDeleteDerivedObject = errors.New("can't delete derived object")
ErrCantDeleteSpace = errors.New("not able to delete space")
)
var (
@ -168,21 +169,31 @@ func (s *settingsObject) Close() error {
return s.SyncTree.Close()
}
var isDerivedRoot = objecttree.IsDerivedRoot
func (s *settingsObject) DeleteObject(id string) (err error) {
s.Lock()
defer s.Unlock()
if s.Id() == id {
err = ErrDeleteSelf
return
return ErrDeleteSelf
}
if s.state.Exists(id) {
err = ErrAlreadyDeleted
return nil
return ErrAlreadyDeleted
}
_, err = s.store.TreeStorage(id)
st, err := s.store.TreeStorage(id)
if err != nil {
err = ErrObjDoesNotExist
return
return ErrObjDoesNotExist
}
root, err := st.Root()
if err != nil {
return ErrObjDoesNotExist
}
isDerived, err := isDerivedRoot(root)
if err != nil {
return ErrObjDoesNotExist
}
if isDerived {
return ErrCantDeleteDerivedObject
}
isSnapshot := DoSnapshot(s.Len())
res, err := s.changeFactory.CreateObjectDeleteChange(id, s.state, isSnapshot)

View file

@ -10,6 +10,8 @@ import (
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/updatelistener"
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage/mock_treestorage"
"github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager"
"github.com/anyproto/any-sync/commonspace/settings/settingsstate"
"github.com/anyproto/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
@ -128,6 +130,9 @@ func TestSettingsObject_Init(t *testing.T) {
}
func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return false, nil
}
fx := newSettingsFixture(t)
defer fx.stop(t)
@ -140,7 +145,9 @@ func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) {
fx.syncTree.EXPECT().Id().Return("syncId")
fx.syncTree.EXPECT().Len().Return(10)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(nil, nil)
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil)
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil)
res := []byte("settingsData")
fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, false).Return(res, nil)
@ -162,9 +169,11 @@ func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) {
}
func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return false, nil
}
fx := newSettingsFixture(t)
defer fx.stop(t)
fx.init(t)
delId := "delId"
DoSnapshot = func(len int) bool {
@ -173,7 +182,9 @@ func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
fx.syncTree.EXPECT().Id().Return("syncId")
fx.syncTree.EXPECT().Len().Return(10)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(nil, nil)
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil)
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil)
res := []byte("settingsData")
fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, true).Return(res, nil)
@ -194,6 +205,26 @@ func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
require.NoError(t, err)
}
func TestSettingsObject_DeleteDerivedObject(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return true, nil
}
fx := newSettingsFixture(t)
defer fx.stop(t)
fx.init(t)
delId := "delId"
DoSnapshot = func(len int) bool {
return true
}
fx.syncTree.EXPECT().Id().Return("syncId")
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil)
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil)
err := fx.doc.DeleteObject(delId)
require.Equal(t, ErrCantDeleteDerivedObject, err)
}
func TestSettingsObject_Rebuild(t *testing.T) {
fx := newSettingsFixture(t)
defer fx.stop(t)