Add some logic in validator
This commit is contained in:
parent
b0432487cc
commit
8cf5acd183
@ -22,6 +22,13 @@ var ErrFailedToDecrypt = errors.New("failed to decrypt key")
|
||||
var ErrUserRemoved = errors.New("user was removed from the document")
|
||||
var ErrDocumentForbidden = errors.New("your user was forbidden access to the document")
|
||||
var ErrUserAlreadyExists = errors.New("user already exists")
|
||||
var ErrNoSuchRecord = errors.New("no such record")
|
||||
var ErrInsufficientPermissions = errors.New("insufficient permissions")
|
||||
|
||||
type UserPermissionPair struct {
|
||||
Identity string
|
||||
Permission aclpb.ACLChangeUserPermissions
|
||||
}
|
||||
|
||||
type ACLState struct {
|
||||
currentReadKeyHash uint64
|
||||
@ -31,6 +38,7 @@ type ACLState struct {
|
||||
signingPubKeyDecoder keys.Decoder
|
||||
encryptionKey encryptionkey.PrivKey
|
||||
identity string
|
||||
permissionsAtRecord map[string][]UserPermissionPair
|
||||
}
|
||||
|
||||
func newACLStateWithIdentity(
|
||||
@ -44,6 +52,7 @@ func newACLStateWithIdentity(
|
||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
||||
signingPubKeyDecoder: decoder,
|
||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +61,7 @@ func newACLState() *ACLState {
|
||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +73,22 @@ func (st *ACLState) UserReadKeys() map[uint64]*symmetric.Key {
|
||||
return st.userReadKeys
|
||||
}
|
||||
|
||||
func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermissionPair, error) {
|
||||
permissions, ok := st.permissionsAtRecord[id]
|
||||
if !ok {
|
||||
return UserPermissionPair{}, ErrNoSuchRecord
|
||||
}
|
||||
|
||||
for _, perm := range permissions {
|
||||
if perm.Identity == identity {
|
||||
return perm, nil
|
||||
}
|
||||
}
|
||||
return UserPermissionPair{}, ErrNoSuchUser
|
||||
}
|
||||
|
||||
func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
||||
// TODO: this should be probably changed
|
||||
aclData := &aclpb.ACLChangeACLData{}
|
||||
|
||||
err = proto.Unmarshal(record.Data, aclData)
|
||||
@ -95,7 +120,21 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
||||
recordWrapper.ParsedModel = aclData
|
||||
}
|
||||
|
||||
return st.applyChangeData(aclData, recordWrapper.Content.CurrentReadKeyHash, recordWrapper.Content.Identity)
|
||||
err = st.applyChangeData(aclData, recordWrapper.Content.CurrentReadKeyHash, recordWrapper.Content.Identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var permissions []UserPermissionPair
|
||||
for _, state := range st.userStates {
|
||||
permission := UserPermissionPair{
|
||||
Identity: state.Identity,
|
||||
Permission: state.Permissions,
|
||||
}
|
||||
permissions = append(permissions, permission)
|
||||
}
|
||||
st.permissionsAtRecord[recordWrapper.Id] = permissions
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uint64, identity string) (err error) {
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package tree
|
||||
|
||||
import "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||
)
|
||||
|
||||
type DocTreeValidator interface {
|
||||
ValidateTree(tree *Tree, aclList list.ACLList) error
|
||||
@ -11,8 +15,44 @@ type docTreeValidator struct{}
|
||||
func newTreeValidator() DocTreeValidator {
|
||||
return &docTreeValidator{}
|
||||
}
|
||||
func (v *docTreeValidator) ValidateTree(tree *Tree, list list.ACLList) error {
|
||||
|
||||
func (v *docTreeValidator) ValidateTree(tree *Tree, aclList list.ACLList) (err error) {
|
||||
// TODO: add validation logic where we check that the change refers to correct acl heads
|
||||
// that means that more recent changes should refer to more recent acl heads
|
||||
return nil
|
||||
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.Id, 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
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
|
||||
@ -92,7 +93,7 @@ func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error
|
||||
|
||||
switch header.DocType {
|
||||
case aclpb.Header_ACL:
|
||||
return tree.BuildACLTreeWithIdentity(t, s.account.Account(), nil)
|
||||
return list.BuildACLListWithIdentity(acc)
|
||||
case aclpb.Header_DocTree:
|
||||
break
|
||||
default:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user