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/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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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)

View file

@ -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

View file

@ -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
}

View file

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