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

Add verifier logic

This commit is contained in:
Mikhail Rakhmanov 2025-05-12 13:17:28 +02:00
parent ab01e874bb
commit c2dc1770b6
No known key found for this signature in database
GPG key ID: DED12CFEF5B8396B
7 changed files with 73 additions and 15 deletions

View file

@ -8,6 +8,7 @@ import (
"github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/commonspace/deletionstate" "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/tree/treestorage"
"github.com/anyproto/any-sync/commonspace/object/treemanager" "github.com/anyproto/any-sync/commonspace/object/treemanager"
"github.com/anyproto/any-sync/commonspace/spacestorage" "github.com/anyproto/any-sync/commonspace/spacestorage"
@ -43,7 +44,7 @@ func (d *deleter) Delete(ctx context.Context) {
} }
} else { } else {
err = d.getter.DeleteTree(ctx, spaceId, id) 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)) log.Error("failed to delete object", zap.Error(err))
continue continue
} }

View file

@ -86,7 +86,8 @@ type AclState struct {
func newAclStateWithKeys( func newAclStateWithKeys(
rootRecord *AclRecord, rootRecord *AclRecord,
key crypto.PrivKey) (st *AclState, err error) { key crypto.PrivKey,
verifier AcceptorVerifier) (st *AclState, err error) {
st = &AclState{ st = &AclState{
id: rootRecord.Id, id: rootRecord.Id,
key: key, key: key,
@ -98,10 +99,7 @@ func newAclStateWithKeys(
pendingRequests: make(map[string]string), pendingRequests: make(map[string]string),
keyStore: crypto.NewKeyStorage(), keyStore: crypto.NewKeyStorage(),
} }
st.contentValidator = &contentValidator{ st.contentValidator = newContentValidator(st.keyStore, st, verifier)
keyStore: st.keyStore,
aclState: st,
}
err = st.applyRoot(rootRecord) err = st.applyRoot(rootRecord)
if err != nil { if err != nil {
return return
@ -109,7 +107,7 @@ func newAclStateWithKeys(
return st, nil return st, nil
} }
func newAclState(rootRecord *AclRecord) (st *AclState, err error) { func newAclState(rootRecord *AclRecord, verifier AcceptorVerifier) (st *AclState, err error) {
st = &AclState{ st = &AclState{
id: rootRecord.Id, id: rootRecord.Id,
keys: make(map[string]AclKeys), keys: make(map[string]AclKeys),
@ -119,10 +117,7 @@ func newAclState(rootRecord *AclRecord) (st *AclState, err error) {
pendingRequests: make(map[string]string), pendingRequests: make(map[string]string),
keyStore: crypto.NewKeyStorage(), keyStore: crypto.NewKeyStorage(),
} }
st.contentValidator = &contentValidator{ st.contentValidator = newContentValidator(st.keyStore, st, verifier)
keyStore: st.keyStore,
aclState: st,
}
err = st.applyRoot(rootRecord) err = st.applyRoot(rootRecord)
if err != nil { if err != nil {
return return
@ -418,7 +413,7 @@ func (st *AclState) Copy() *AclState {
newSt.readKeyChanges = append(newSt.readKeyChanges, st.readKeyChanges...) newSt.readKeyChanges = append(newSt.readKeyChanges, st.readKeyChanges...)
newSt.list = st.list newSt.list = st.list
newSt.lastRecordId = st.lastRecordId newSt.lastRecordId = st.lastRecordId
newSt.contentValidator = newContentValidator(newSt.keyStore, newSt) newSt.contentValidator = newContentValidator(newSt.keyStore, newSt, st.list.verifier)
return newSt return newSt
} }

View file

@ -29,12 +29,12 @@ func (sb *aclStateBuilder) Build(records []*AclRecord, list *aclList) (state *Ac
return nil, ErrIncorrectRecordSequence return nil, ErrIncorrectRecordSequence
} }
if sb.privKey != nil { if sb.privKey != nil {
state, err = newAclStateWithKeys(records[0], sb.privKey) state, err = newAclStateWithKeys(records[0], sb.privKey, list.verifier)
if err != nil { if err != nil {
return return
} }
} else { } else {
state, err = newAclState(records[0]) state, err = newAclState(records[0], list.verifier)
if err != nil { if err != nil {
return return
} }

View file

@ -28,6 +28,7 @@ type RWLocker interface {
type AcceptorVerifier interface { type AcceptorVerifier interface {
VerifyAcceptor(rec *consensusproto.RawRecord) (err error) VerifyAcceptor(rec *consensusproto.RawRecord) (err error)
ShouldValidate() bool
} }
type NoOpAcceptorVerifier struct { type NoOpAcceptorVerifier struct {
@ -37,6 +38,10 @@ func (n NoOpAcceptorVerifier) VerifyAcceptor(rec *consensusproto.RawRecord) (err
return nil return nil
} }
func (n NoOpAcceptorVerifier) ShouldValidate() bool {
return true
}
type AclList interface { type AclList interface {
RWLocker RWLocker
Id() string Id() string
@ -75,6 +80,7 @@ type aclList struct {
keyStorage crypto.KeyStorage keyStorage crypto.KeyStorage
aclState *AclState aclState *AclState
storage Storage storage Storage
verifier AcceptorVerifier
sync.RWMutex sync.RWMutex
} }
@ -159,6 +165,7 @@ func build(deps internalDeps) (list AclList, err error) {
stateBuilder: stateBuilder, stateBuilder: stateBuilder,
recordBuilder: recBuilder, recordBuilder: recBuilder,
storage: storage, storage: storage,
verifier: deps.acceptorVerifier,
id: id, id: id,
} }
stateBuilder.Init(id) stateBuilder.Init(id)

View file

@ -27,16 +27,21 @@ type ContentValidator interface {
type contentValidator struct { type contentValidator struct {
keyStore crypto.KeyStorage keyStore crypto.KeyStorage
aclState *AclState aclState *AclState
verifier AcceptorVerifier
} }
func newContentValidator(keyStore crypto.KeyStorage, aclState *AclState) ContentValidator { func newContentValidator(keyStore crypto.KeyStorage, aclState *AclState, verifier AcceptorVerifier) ContentValidator {
return &contentValidator{ return &contentValidator{
keyStore: keyStore, keyStore: keyStore,
aclState: aclState, aclState: aclState,
verifier: verifier,
} }
} }
func (c *contentValidator) ValidatePermissionChanges(ch *aclrecordproto.AclAccountPermissionChanges, authorIdentity crypto.PubKey) (err error) { func (c *contentValidator) ValidatePermissionChanges(ch *aclrecordproto.AclAccountPermissionChanges, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
for _, ch := range ch.Changes { for _, ch := range ch.Changes {
err := c.ValidatePermissionChange(ch, authorIdentity) err := c.ValidatePermissionChange(ch, authorIdentity)
if err != nil { 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) { func (c *contentValidator) ValidateAccountsAdd(ch *aclrecordproto.AclAccountsAdd, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateInviteJoin(ch *aclrecordproto.AclAccountInviteJoin, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).NoPermissions() { if !c.aclState.Permissions(authorIdentity).NoPermissions() {
return ErrInsufficientPermissions return ErrInsufficientPermissions
} }
@ -111,6 +122,9 @@ func (c *contentValidator) ValidateInviteJoin(ch *aclrecordproto.AclAccountInvit
} }
func (c *contentValidator) ValidateAclRecordContents(ch *AclRecord) (err error) { func (c *contentValidator) ValidateAclRecordContents(ch *AclRecord) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if ch.PrevId != c.aclState.lastRecordId { if ch.PrevId != c.aclState.lastRecordId {
return ErrIncorrectRecordSequence 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) { func (c *contentValidator) ValidatePermissionChange(ch *aclrecordproto.AclAccountPermissionChange, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateInvite(ch *aclrecordproto.AclAccountInvite, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateInviteRevoke(ch *aclrecordproto.AclAccountInviteRevoke, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { 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] invite, exists := c.aclState.invites[ch.InviteRecordId]
if !exists { if !exists {
return ErrNoSuchInvite 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) { func (c *contentValidator) ValidateRequestAccept(ch *aclrecordproto.AclAccountRequestAccept, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateRequestDecline(ch *aclrecordproto.AclAccountRequestDecline, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { 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] rec, exists := c.aclState.requestRecords[ch.RecordId]
if !exists { if !exists {
return ErrNoSuchRequest 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) { func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRemove, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() { if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRequestRemove, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
if c.aclState.Permissions(authorIdentity).NoPermissions() { if c.aclState.Permissions(authorIdentity).NoPermissions() {
return ErrInsufficientPermissions 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) { func (c *contentValidator) ValidateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, authorIdentity crypto.PubKey) (err error) {
if !c.verifier.ShouldValidate() {
return nil
}
return c.validateReadKeyChange(ch, nil) return c.validateReadKeyChange(ch, nil)
} }
func (c *contentValidator) validateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, removedUsers map[string]struct{}) (err error) { 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) _, err = c.keyStore.PubKeyFromProto(ch.MetadataPubKey)
if err != nil { if err != nil {
return ErrNoMetadataKey return ErrNoMetadataKey

View file

@ -22,3 +22,7 @@ func (a *AlwaysAccept) Name() string {
func (a *AlwaysAccept) VerifyAcceptor(_ *consensusproto.RawRecord) error { func (a *AlwaysAccept) VerifyAcceptor(_ *consensusproto.RawRecord) error {
return nil return nil
} }
func (a *AlwaysAccept) ShouldValidate() bool {
return true
}

View file

@ -50,3 +50,7 @@ func (r *recordVerifier) VerifyAcceptor(rec *consensusproto.RawRecord) (err erro
} }
return nil return nil
} }
func (r *recordVerifier) ShouldValidate() bool {
return false
}