59 lines
1.6 KiB
Go
59 lines
1.6 KiB
Go
package tree
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
|
)
|
|
|
|
type ObjectTreeValidator interface {
|
|
// ValidateTree should always be entered while holding a read lock on ACLList
|
|
ValidateTree(tree *Tree, aclList list.ACLList) error
|
|
}
|
|
|
|
type objectTreeValidator struct{}
|
|
|
|
func newTreeValidator() ObjectTreeValidator {
|
|
return &objectTreeValidator{}
|
|
}
|
|
|
|
func (v *objectTreeValidator) ValidateTree(tree *Tree, aclList list.ACLList) (err error) {
|
|
|
|
var (
|
|
perm list.UserPermissionPair
|
|
state = aclList.ACLState()
|
|
)
|
|
|
|
tree.Iterate(tree.RootId(), func(c *Change) (isContinue bool) {
|
|
// checking if the user could write
|
|
perm, err = state.PermissionsAtRecord(c.Content.AclHeadId, c.Content.Identity)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
if perm.Permission != aclpb.ACLChange_Writer && perm.Permission != aclpb.ACLChange_Admin {
|
|
err = list.ErrInsufficientPermissions
|
|
return false
|
|
}
|
|
|
|
// checking if the change refers to later acl heads than its previous ids
|
|
for _, id := range c.PreviousIds {
|
|
prevChange := tree.attached[id]
|
|
if prevChange.Content.AclHeadId == c.Content.AclHeadId {
|
|
continue
|
|
}
|
|
var after bool
|
|
after, err = aclList.IsAfter(c.Content.AclHeadId, prevChange.Content.AclHeadId)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
if !after {
|
|
err = fmt.Errorf("current acl head id (%s) should be after each of the previous ones (%s)", c.Content.AclHeadId, prevChange.Content.AclHeadId)
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
return err
|
|
}
|