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 ErrUserRemoved = errors.New("user was removed from the document")
|
||||||
var ErrDocumentForbidden = errors.New("your user was forbidden access to the document")
|
var ErrDocumentForbidden = errors.New("your user was forbidden access to the document")
|
||||||
var ErrUserAlreadyExists = errors.New("user already exists")
|
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 {
|
type ACLState struct {
|
||||||
currentReadKeyHash uint64
|
currentReadKeyHash uint64
|
||||||
@ -31,6 +38,7 @@ type ACLState struct {
|
|||||||
signingPubKeyDecoder keys.Decoder
|
signingPubKeyDecoder keys.Decoder
|
||||||
encryptionKey encryptionkey.PrivKey
|
encryptionKey encryptionkey.PrivKey
|
||||||
identity string
|
identity string
|
||||||
|
permissionsAtRecord map[string][]UserPermissionPair
|
||||||
}
|
}
|
||||||
|
|
||||||
func newACLStateWithIdentity(
|
func newACLStateWithIdentity(
|
||||||
@ -44,14 +52,16 @@ func newACLStateWithIdentity(
|
|||||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
||||||
signingPubKeyDecoder: decoder,
|
signingPubKeyDecoder: decoder,
|
||||||
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newACLState() *ACLState {
|
func newACLState() *ACLState {
|
||||||
return &ACLState{
|
return &ACLState{
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
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
|
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) {
|
func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
||||||
|
// TODO: this should be probably changed
|
||||||
aclData := &aclpb.ACLChangeACLData{}
|
aclData := &aclpb.ACLChangeACLData{}
|
||||||
|
|
||||||
err = proto.Unmarshal(record.Data, aclData)
|
err = proto.Unmarshal(record.Data, aclData)
|
||||||
@ -95,7 +120,21 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
|||||||
recordWrapper.ParsedModel = aclData
|
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) {
|
func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uint64, identity string) (err error) {
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
package tree
|
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 {
|
type DocTreeValidator interface {
|
||||||
ValidateTree(tree *Tree, aclList list.ACLList) error
|
ValidateTree(tree *Tree, aclList list.ACLList) error
|
||||||
@ -11,8 +15,44 @@ type docTreeValidator struct{}
|
|||||||
func newTreeValidator() DocTreeValidator {
|
func newTreeValidator() DocTreeValidator {
|
||||||
return &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
|
// 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
|
// 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"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"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/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/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
|
"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 {
|
switch header.DocType {
|
||||||
case aclpb.Header_ACL:
|
case aclpb.Header_ACL:
|
||||||
return tree.BuildACLTreeWithIdentity(t, s.account.Account(), nil)
|
return list.BuildACLListWithIdentity(acc)
|
||||||
case aclpb.Header_DocTree:
|
case aclpb.Header_DocTree:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user