From c2dc1770b61c0d487edca4c867a8c7396e5bc218 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Mon, 12 May 2025 13:17:28 +0200 Subject: [PATCH] Add verifier logic --- commonspace/deletionmanager/deleter.go | 3 +- commonspace/object/acl/list/aclstate.go | 17 +++---- .../object/acl/list/aclstatebuilder.go | 4 +- commonspace/object/acl/list/list.go | 7 +++ commonspace/object/acl/list/validator.go | 49 ++++++++++++++++++- .../object/acl/recordverifier/alwaysaccept.go | 4 ++ .../acl/recordverifier/recordverifier.go | 4 ++ 7 files changed, 73 insertions(+), 15 deletions(-) diff --git a/commonspace/deletionmanager/deleter.go b/commonspace/deletionmanager/deleter.go index b4fae7b2..e252d646 100644 --- a/commonspace/deletionmanager/deleter.go +++ b/commonspace/deletionmanager/deleter.go @@ -8,6 +8,7 @@ import ( "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/commonspace/deletionstate" + "github.com/anyproto/any-sync/commonspace/object/tree/synctree" "github.com/anyproto/any-sync/commonspace/object/tree/treestorage" "github.com/anyproto/any-sync/commonspace/object/treemanager" "github.com/anyproto/any-sync/commonspace/spacestorage" @@ -43,7 +44,7 @@ func (d *deleter) Delete(ctx context.Context) { } } else { err = d.getter.DeleteTree(ctx, spaceId, id) - if err != nil && !errors.Is(err, spacestorage.ErrTreeStorageAlreadyDeleted) { + if err != nil && !errors.Is(err, spacestorage.ErrTreeStorageAlreadyDeleted) && !errors.Is(err, synctree.ErrSyncTreeDeleted) { log.Error("failed to delete object", zap.Error(err)) continue } diff --git a/commonspace/object/acl/list/aclstate.go b/commonspace/object/acl/list/aclstate.go index e6088ec7..1afb8892 100644 --- a/commonspace/object/acl/list/aclstate.go +++ b/commonspace/object/acl/list/aclstate.go @@ -86,7 +86,8 @@ type AclState struct { func newAclStateWithKeys( rootRecord *AclRecord, - key crypto.PrivKey) (st *AclState, err error) { + key crypto.PrivKey, + verifier AcceptorVerifier) (st *AclState, err error) { st = &AclState{ id: rootRecord.Id, key: key, @@ -98,10 +99,7 @@ func newAclStateWithKeys( pendingRequests: make(map[string]string), keyStore: crypto.NewKeyStorage(), } - st.contentValidator = &contentValidator{ - keyStore: st.keyStore, - aclState: st, - } + st.contentValidator = newContentValidator(st.keyStore, st, verifier) err = st.applyRoot(rootRecord) if err != nil { return @@ -109,7 +107,7 @@ func newAclStateWithKeys( return st, nil } -func newAclState(rootRecord *AclRecord) (st *AclState, err error) { +func newAclState(rootRecord *AclRecord, verifier AcceptorVerifier) (st *AclState, err error) { st = &AclState{ id: rootRecord.Id, keys: make(map[string]AclKeys), @@ -119,10 +117,7 @@ func newAclState(rootRecord *AclRecord) (st *AclState, err error) { pendingRequests: make(map[string]string), keyStore: crypto.NewKeyStorage(), } - st.contentValidator = &contentValidator{ - keyStore: st.keyStore, - aclState: st, - } + st.contentValidator = newContentValidator(st.keyStore, st, verifier) err = st.applyRoot(rootRecord) if err != nil { return @@ -418,7 +413,7 @@ func (st *AclState) Copy() *AclState { newSt.readKeyChanges = append(newSt.readKeyChanges, st.readKeyChanges...) newSt.list = st.list newSt.lastRecordId = st.lastRecordId - newSt.contentValidator = newContentValidator(newSt.keyStore, newSt) + newSt.contentValidator = newContentValidator(newSt.keyStore, newSt, st.list.verifier) return newSt } diff --git a/commonspace/object/acl/list/aclstatebuilder.go b/commonspace/object/acl/list/aclstatebuilder.go index 2b7317f7..767a0947 100644 --- a/commonspace/object/acl/list/aclstatebuilder.go +++ b/commonspace/object/acl/list/aclstatebuilder.go @@ -29,12 +29,12 @@ func (sb *aclStateBuilder) Build(records []*AclRecord, list *aclList) (state *Ac return nil, ErrIncorrectRecordSequence } if sb.privKey != nil { - state, err = newAclStateWithKeys(records[0], sb.privKey) + state, err = newAclStateWithKeys(records[0], sb.privKey, list.verifier) if err != nil { return } } else { - state, err = newAclState(records[0]) + state, err = newAclState(records[0], list.verifier) if err != nil { return } diff --git a/commonspace/object/acl/list/list.go b/commonspace/object/acl/list/list.go index 6640efbd..4890f24a 100644 --- a/commonspace/object/acl/list/list.go +++ b/commonspace/object/acl/list/list.go @@ -28,6 +28,7 @@ type RWLocker interface { type AcceptorVerifier interface { VerifyAcceptor(rec *consensusproto.RawRecord) (err error) + ShouldValidate() bool } type NoOpAcceptorVerifier struct { @@ -37,6 +38,10 @@ func (n NoOpAcceptorVerifier) VerifyAcceptor(rec *consensusproto.RawRecord) (err return nil } +func (n NoOpAcceptorVerifier) ShouldValidate() bool { + return true +} + type AclList interface { RWLocker Id() string @@ -75,6 +80,7 @@ type aclList struct { keyStorage crypto.KeyStorage aclState *AclState storage Storage + verifier AcceptorVerifier sync.RWMutex } @@ -159,6 +165,7 @@ func build(deps internalDeps) (list AclList, err error) { stateBuilder: stateBuilder, recordBuilder: recBuilder, storage: storage, + verifier: deps.acceptorVerifier, id: id, } stateBuilder.Init(id) diff --git a/commonspace/object/acl/list/validator.go b/commonspace/object/acl/list/validator.go index f17fce99..c927c557 100644 --- a/commonspace/object/acl/list/validator.go +++ b/commonspace/object/acl/list/validator.go @@ -27,16 +27,21 @@ type ContentValidator interface { type contentValidator struct { keyStore crypto.KeyStorage aclState *AclState + verifier AcceptorVerifier } -func newContentValidator(keyStore crypto.KeyStorage, aclState *AclState) ContentValidator { +func newContentValidator(keyStore crypto.KeyStorage, aclState *AclState, verifier AcceptorVerifier) ContentValidator { return &contentValidator{ keyStore: keyStore, aclState: aclState, + verifier: verifier, } } func (c *contentValidator) ValidatePermissionChanges(ch *aclrecordproto.AclAccountPermissionChanges, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } for _, ch := range ch.Changes { err := c.ValidatePermissionChange(ch, authorIdentity) if err != nil { @@ -47,6 +52,9 @@ func (c *contentValidator) ValidatePermissionChanges(ch *aclrecordproto.AclAccou } func (c *contentValidator) ValidateAccountsAdd(ch *aclrecordproto.AclAccountsAdd, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -70,6 +78,9 @@ func (c *contentValidator) ValidateAccountsAdd(ch *aclrecordproto.AclAccountsAdd } func (c *contentValidator) ValidateInviteJoin(ch *aclrecordproto.AclAccountInviteJoin, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).NoPermissions() { return ErrInsufficientPermissions } @@ -111,6 +122,9 @@ func (c *contentValidator) ValidateInviteJoin(ch *aclrecordproto.AclAccountInvit } func (c *contentValidator) ValidateAclRecordContents(ch *AclRecord) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if ch.PrevId != c.aclState.lastRecordId { return ErrIncorrectRecordSequence } @@ -156,6 +170,9 @@ func (c *contentValidator) validateAclRecordContent(ch *aclrecordproto.AclConten } func (c *contentValidator) ValidatePermissionChange(ch *aclrecordproto.AclAccountPermissionChange, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -195,6 +212,9 @@ func (c *contentValidator) ValidatePermissionChange(ch *aclrecordproto.AclAccoun } func (c *contentValidator) ValidateInvite(ch *aclrecordproto.AclAccountInvite, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -207,6 +227,9 @@ func (c *contentValidator) ValidateInvite(ch *aclrecordproto.AclAccountInvite, a } func (c *contentValidator) ValidateInviteRevoke(ch *aclrecordproto.AclAccountInviteRevoke, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -218,6 +241,9 @@ func (c *contentValidator) ValidateInviteRevoke(ch *aclrecordproto.AclAccountInv } func (c *contentValidator) ValidateRequestJoin(ch *aclrecordproto.AclAccountRequestJoin, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } invite, exists := c.aclState.invites[ch.InviteRecordId] if !exists { return ErrNoSuchInvite @@ -253,6 +279,9 @@ func (c *contentValidator) ValidateRequestJoin(ch *aclrecordproto.AclAccountRequ } func (c *contentValidator) ValidateRequestAccept(ch *aclrecordproto.AclAccountRequestAccept, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -274,6 +303,9 @@ func (c *contentValidator) ValidateRequestAccept(ch *aclrecordproto.AclAccountRe } func (c *contentValidator) ValidateRequestDecline(ch *aclrecordproto.AclAccountRequestDecline, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -285,6 +317,9 @@ func (c *contentValidator) ValidateRequestDecline(ch *aclrecordproto.AclAccountR } func (c *contentValidator) ValidateRequestCancel(ch *aclrecordproto.AclAccountRequestCancel, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } rec, exists := c.aclState.requestRecords[ch.RecordId] if !exists { return ErrNoSuchRequest @@ -296,6 +331,9 @@ func (c *contentValidator) ValidateRequestCancel(ch *aclrecordproto.AclAccountRe } func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRemove, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { return ErrInsufficientPermissions } @@ -325,6 +363,9 @@ func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRe } func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRequestRemove, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } if c.aclState.Permissions(authorIdentity).NoPermissions() { return ErrInsufficientPermissions } @@ -338,10 +379,16 @@ func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRe } func (c *contentValidator) ValidateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, authorIdentity crypto.PubKey) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } return c.validateReadKeyChange(ch, nil) } func (c *contentValidator) validateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, removedUsers map[string]struct{}) (err error) { + if !c.verifier.ShouldValidate() { + return nil + } _, err = c.keyStore.PubKeyFromProto(ch.MetadataPubKey) if err != nil { return ErrNoMetadataKey diff --git a/commonspace/object/acl/recordverifier/alwaysaccept.go b/commonspace/object/acl/recordverifier/alwaysaccept.go index c5712d2a..4dcdffe5 100644 --- a/commonspace/object/acl/recordverifier/alwaysaccept.go +++ b/commonspace/object/acl/recordverifier/alwaysaccept.go @@ -22,3 +22,7 @@ func (a *AlwaysAccept) Name() string { func (a *AlwaysAccept) VerifyAcceptor(_ *consensusproto.RawRecord) error { return nil } + +func (a *AlwaysAccept) ShouldValidate() bool { + return true +} diff --git a/commonspace/object/acl/recordverifier/recordverifier.go b/commonspace/object/acl/recordverifier/recordverifier.go index 693e43d7..222b14c0 100644 --- a/commonspace/object/acl/recordverifier/recordverifier.go +++ b/commonspace/object/acl/recordverifier/recordverifier.go @@ -50,3 +50,7 @@ func (r *recordVerifier) VerifyAcceptor(rec *consensusproto.RawRecord) (err erro } return nil } + +func (r *recordVerifier) ShouldValidate() bool { + return false +}