diff --git a/client/errors.go b/client/errors.go index 60ccac9669..1da4882ca5 100644 --- a/client/errors.go +++ b/client/errors.go @@ -44,6 +44,8 @@ var ( ErrFieldNotObject = errors.New("trying to access field on a non object type") ErrValueTypeMismatch = errors.New("value does not match indicated type") ErrDocumentNotFound = errors.New("no document for the given ID exists") + ErrInvalidACPPermToDeleteDocument = errors.New("invalid acp permission to delete the document") + ErrInvalidACPPermToUpdateDocument = errors.New("invalid acp permission to update the document") ErrInvalidUpdateTarget = errors.New("the target document to update is of invalid type") ErrInvalidUpdater = errors.New("the updater of a document is of invalid type") ErrInvalidDeleteTarget = errors.New("the target document to delete is of invalid type") diff --git a/db/collection.go b/db/collection.go index d3e61b5745..85d0789358 100644 --- a/db/collection.go +++ b/db/collection.go @@ -24,6 +24,7 @@ import ( "github.com/lens-vm/lens/host-go/config/model" "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/acp" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" @@ -1074,7 +1075,20 @@ func (c *collection) Update(ctx context.Context, doc *client.Document) error { // Should probably be smart about the update due to the MerkleCRDT overhead, shouldn't // add to the bloat. func (c *collection) update(ctx context.Context, txn datastore.Txn, doc *client.Document) error { - _, err := c.save(ctx, txn, doc, false) + // Stop the update if the correct permissions aren't there. + canUpdate, err := c.checkDocPermissionedAccess( + ctx, + acp.WritePermission, + doc.ID().String(), + ) + if err != nil { + return err + } + if !canUpdate { + return client.ErrInvalidACPPermToDeleteDocument + } + + _, err = c.save(ctx, txn, doc, false) if err != nil { return err } @@ -1113,6 +1127,9 @@ func (c *collection) Save(ctx context.Context, doc *client.Document) error { return c.commitImplicitTxn(ctx, txn) } +// save saves the document state. save MUST not be called outside the `c.create` +// and `c.update` methods as we wrap the acp logic within those methods. Calling +// save elsewhere could cause the omission of acp checks. func (c *collection) save( ctx context.Context, txn datastore.Txn, @@ -1400,6 +1417,10 @@ func (c *collection) exists( return true, false, nil } +// saveCompositeToMerkleCRDT saves the composite to the merkle CRDT. +// saveCompositeToMerkleCRDT MUST not be called outside the `c.save` +// and `c.applyDelete` methods as we wrap the acp logic around those methods. +// Calling it elsewhere could cause the omission of acp checks. func (c *collection) saveCompositeToMerkleCRDT( ctx context.Context, txn datastore.Txn, diff --git a/db/collection_delete.go b/db/collection_delete.go index 6c360d09c0..cde25d92b7 100644 --- a/db/collection_delete.go +++ b/db/collection_delete.go @@ -13,6 +13,7 @@ package db import ( "context" + "github.com/sourcenetwork/defradb/acp" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" @@ -241,6 +242,19 @@ func (c *collection) applyDelete( return NewErrDocumentDeleted(primaryKey.DocID) } + // Stop deletion of document if the correct permissions aren't there. + canDelete, err := c.checkDocPermissionedAccess( + ctx, + acp.WritePermission, + primaryKey.DocID, + ) + if err != nil { + return err + } + if !canDelete { + return client.ErrInvalidACPPermToDeleteDocument + } + dsKey := primaryKey.ToDataStoreKey() headset := clock.NewHeadSet( diff --git a/db/collection_update.go b/db/collection_update.go index 58e6e9086f..bbf42a4fea 100644 --- a/db/collection_update.go +++ b/db/collection_update.go @@ -141,7 +141,7 @@ func (c *collection) updateWithDocID( return nil, err } - _, err = c.save(ctx, txn, doc, false) + err = c.update(ctx, txn, doc) if err != nil { return nil, err } @@ -189,7 +189,7 @@ func (c *collection) updateWithIDs( return nil, err } - _, err = c.save(ctx, txn, doc, false) + err = c.update(ctx, txn, doc) if err != nil { return nil, err } @@ -277,7 +277,7 @@ func (c *collection) updateWithFilter( } } - _, err = c.save(ctx, txn, doc, false) + err = c.update(ctx, txn, doc) if err != nil { return nil, err }