Add raw record to list

This commit is contained in:
mcrakhman 2022-10-28 12:04:23 +02:00 committed by Mikhail Iudin
parent 5f6e51c15a
commit 2946c050b9
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
5 changed files with 93 additions and 13 deletions

View File

@ -11,6 +11,7 @@ import (
type ACLRecordBuilder interface {
ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error)
BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *ACLState) (rec *aclrecordproto.RawACLRecord, err error)
}
type aclRecordBuilder struct {

View File

@ -30,6 +30,7 @@ var ErrInsufficientPermissions = errors.New("insufficient permissions")
var ErrNoReadKey = errors.New("acl state doesn't have a read key")
var ErrInvalidSignature = errors.New("signature is invalid")
var ErrIncorrectRoot = errors.New("incorrect root")
var ErrIncorrectRecordSequence = errors.New("incorrect prev id of a record")
type UserPermissionPair struct {
Identity string
@ -48,6 +49,7 @@ type ACLState struct {
identity string
permissionsAtRecord map[string][]UserPermissionPair
lastRecordId string
keychain *common.Keychain
}
@ -114,15 +116,28 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
}
func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
defer func() {
if err == nil {
st.lastRecordId = record.Id
}
}()
if st.lastRecordId != record.PrevId {
err = ErrIncorrectRecordSequence
return
}
if record.Id == st.id {
root, ok := record.Model.(*aclrecordproto.ACLRoot)
if !ok {
return ErrIncorrectRoot
}
err = st.applyRoot(root)
if err != nil {
return
}
st.permissionsAtRecord[record.Id] = []UserPermissionPair{
{Identity: string(root.Identity), Permission: aclrecordproto.ACLUserPermissions_Admin},
}
return st.applyRoot(root)
return
}
aclData := &aclrecordproto.ACLData{}
@ -152,7 +167,7 @@ func (st *ACLState) applyRecord(record *ACLRecord) (err error) {
}
st.permissionsAtRecord[record.Id] = permissions
return nil
return
}
func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
@ -170,6 +185,7 @@ func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
Permissions: aclrecordproto.ACLUserPermissions_Admin,
}
st.userStates[string(root.Identity)] = userState
st.totalReadKeys++
return
}
@ -203,7 +219,6 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error
}
st.currentReadKeyHash = root.CurrentReadKeyHash
st.userReadKeys[root.CurrentReadKeyHash] = readKey
st.totalReadKeys++
return
}

View File

@ -45,3 +45,13 @@ func (sb *aclStateBuilder) Build(records []*ACLRecord) (state *ACLState, err err
return state, err
}
func (sb *aclStateBuilder) Append(state *ACLState, records []*ACLRecord) (err error) {
for _, rec := range records {
err = state.applyRecord(rec)
if err != nil {
return
}
}
return
}

View File

@ -29,6 +29,7 @@ type ACLList interface {
Records() []*ACLRecord
ACLState() *ACLState
IsAfter(first string, second string) (bool, error)
AddRawRecords(ctx context.Context, rec []*aclrecordproto.RawACLRecordWithId) (err error)
Head() *ACLRecord
Get(id string) (*ACLRecord, error)
Iterate(iterFunc IterFunc)
@ -42,9 +43,11 @@ type aclList struct {
indexes map[string]int
id string
builder *aclStateBuilder
aclState *ACLState
keychain *common.Keychain
stateBuilder *aclStateBuilder
recordBuilder ACLRecordBuilder
aclState *ACLState
keychain *common.Keychain
storage storage.ListStorage
sync.RWMutex
}
@ -120,13 +123,15 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
}
list = &aclList{
root: aclRecRoot.Model.(*aclrecordproto.ACLRoot),
records: records,
indexes: indexes,
builder: stateBuilder,
aclState: state,
id: id,
RWMutex: sync.RWMutex{},
root: aclRecRoot.Model.(*aclrecordproto.ACLRoot),
records: records,
indexes: indexes,
stateBuilder: stateBuilder,
recordBuilder: recBuilder,
aclState: state,
storage: storage,
id: id,
RWMutex: sync.RWMutex{},
}
return
}
@ -143,6 +148,40 @@ func (a *aclList) Root() *aclrecordproto.ACLRoot {
return a.root
}
func (a *aclList) AddRawRecords(ctx context.Context, records []*aclrecordproto.RawACLRecordWithId) (err error) {
if len(records) == 0 {
return
}
// converting and verifying
var aclRecords []*ACLRecord
for _, rec := range records {
var record *ACLRecord
record, err = a.recordBuilder.ConvertFromRaw(rec)
if err != nil {
return
}
aclRecords = append(aclRecords, record)
}
// trying to append them to state
err = a.stateBuilder.Append(a.aclState, aclRecords)
if err != nil {
return
}
// saving to storage
for _, rec := range records {
err = a.storage.AddRawRecord(ctx, rec)
if err != nil {
return
}
}
// setting new head
err = a.storage.SetHead(records[len(records)-1].Id)
return
}
func (a *aclList) ACLState() *ACLState {
return a.aclState
}

View File

@ -5,6 +5,7 @@
package mock_list
import (
context "context"
reflect "reflect"
aclrecordproto "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
@ -49,6 +50,20 @@ func (mr *MockACLListMockRecorder) ACLState() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ACLState", reflect.TypeOf((*MockACLList)(nil).ACLState))
}
// AddRawRecords mocks base method.
func (m *MockACLList) AddRawRecords(arg0 context.Context, arg1 []*aclrecordproto.RawACLRecordWithId) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddRawRecords", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// AddRawRecords indicates an expected call of AddRawRecords.
func (mr *MockACLListMockRecorder) AddRawRecords(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawRecords", reflect.TypeOf((*MockACLList)(nil).AddRawRecords), arg0, arg1)
}
// Close mocks base method.
func (m *MockACLList) Close() error {
m.ctrl.T.Helper()