mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-08 05:57:03 +09:00
aclService: OwnerId, Permissions
This commit is contained in:
parent
19798f2295
commit
151dd9508d
5 changed files with 231 additions and 8 deletions
17
acl/acl.go
17
acl/acl.go
|
@ -1,3 +1,4 @@
|
|||
//go:generate mockgen -destination mock_acl/mock_acl.go github.com/anyproto/any-sync/acl AclService
|
||||
package acl
|
||||
|
||||
import (
|
||||
|
@ -21,13 +22,15 @@ const CName = "coordinator.acl"
|
|||
|
||||
var log = logger.NewNamed(CName)
|
||||
|
||||
func New() Acl {
|
||||
func New() AclService {
|
||||
return &aclService{}
|
||||
}
|
||||
|
||||
type Acl interface {
|
||||
type AclService interface {
|
||||
AddRecord(ctx context.Context, spaceId string, rec *consensusproto.RawRecord) (result *consensusproto.RawRecordWithId, err error)
|
||||
RecordsAfter(ctx context.Context, spaceId, aclHead string) (result []*consensusproto.RawRecordWithId, err error)
|
||||
Permissions(ctx context.Context, identity crypto.PubKey, spaceId string) (res list.AclPermissions, err error)
|
||||
OwnerPubKey(ctx context.Context, spaceId string) (ownerIdentity crypto.PubKey, err error)
|
||||
app.ComponentRunnable
|
||||
}
|
||||
|
||||
|
@ -96,6 +99,16 @@ func (as *aclService) RecordsAfter(ctx context.Context, spaceId, aclHead string)
|
|||
return acl.RecordsAfter(ctx, aclHead)
|
||||
}
|
||||
|
||||
func (as *aclService) OwnerPubKey(ctx context.Context, spaceId string) (ownerIdentity crypto.PubKey, err error) {
|
||||
acl, err := as.get(ctx, spaceId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
acl.RLock()
|
||||
defer acl.RUnlock()
|
||||
return acl.AclState().OwnerPubKey()
|
||||
}
|
||||
|
||||
func (as *aclService) Permissions(ctx context.Context, identity crypto.PubKey, spaceId string) (res list.AclPermissions, err error) {
|
||||
acl, err := as.get(ctx, spaceId)
|
||||
if err != nil {
|
||||
|
|
|
@ -103,13 +103,45 @@ func TestAclService_RecordsAfter(t *testing.T) {
|
|||
assert.Len(t, res, 1)
|
||||
}
|
||||
|
||||
func TestAclService(t *testing.T) {
|
||||
ownerKeys, err := accountdata.NewRandom()
|
||||
require.NoError(t, err)
|
||||
spaceId := "spaceId"
|
||||
ownerAcl, err := list.NewTestDerivedAcl(spaceId, ownerKeys)
|
||||
require.NoError(t, err)
|
||||
|
||||
fx := newFixture(t)
|
||||
defer fx.finish(t)
|
||||
|
||||
fx.consCl.EXPECT().Watch(spaceId, gomock.Any()).DoAndReturn(func(spaceId string, w consensusclient.Watcher) error {
|
||||
go func() {
|
||||
w.AddConsensusRecords([]*consensusproto.RawRecordWithId{
|
||||
ownerAcl.Root(),
|
||||
})
|
||||
}()
|
||||
return nil
|
||||
})
|
||||
fx.consCl.EXPECT().UnWatch(spaceId)
|
||||
|
||||
t.Run("permissions", func(t *testing.T) {
|
||||
res, err := fx.Permissions(ctx, ownerKeys.SignKey.GetPublic(), spaceId)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, res.IsOwner())
|
||||
})
|
||||
t.Run("ownerPUbKey", func(t *testing.T) {
|
||||
res, err := fx.OwnerPubKey(ctx, spaceId)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, ownerKeys.SignKey.GetPublic().Account(), res.Account())
|
||||
})
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
ctrl := gomock.NewController(t)
|
||||
fx := &fixture{
|
||||
a: new(app.App),
|
||||
ctrl: ctrl,
|
||||
consCl: mock_consensusclient.NewMockService(ctrl),
|
||||
Acl: New(),
|
||||
a: new(app.App),
|
||||
ctrl: ctrl,
|
||||
consCl: mock_consensusclient.NewMockService(ctrl),
|
||||
AclService: New(),
|
||||
}
|
||||
|
||||
fx.consCl.EXPECT().Name().Return(consensusclient.CName).AnyTimes()
|
||||
|
@ -117,7 +149,7 @@ func newFixture(t *testing.T) *fixture {
|
|||
fx.consCl.EXPECT().Run(gomock.Any()).AnyTimes()
|
||||
fx.consCl.EXPECT().Close(gomock.Any()).AnyTimes()
|
||||
|
||||
fx.a.Register(fx.consCl).Register(fx.Acl).Register(&accounttest.AccountTestService{})
|
||||
fx.a.Register(fx.consCl).Register(fx.AclService).Register(&accounttest.AccountTestService{})
|
||||
|
||||
require.NoError(t, fx.a.Start(ctx))
|
||||
return fx
|
||||
|
@ -127,7 +159,7 @@ type fixture struct {
|
|||
a *app.App
|
||||
ctrl *gomock.Controller
|
||||
consCl *mock_consensusclient.MockService
|
||||
Acl
|
||||
AclService
|
||||
}
|
||||
|
||||
func (fx *fixture) finish(t *testing.T) {
|
||||
|
|
160
acl/mock_acl/mock_acl.go
Normal file
160
acl/mock_acl/mock_acl.go
Normal file
|
@ -0,0 +1,160 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/anyproto/any-sync/acl (interfaces: AclService)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -destination mock_acl/mock_acl.go github.com/anyproto/any-sync/acl AclService
|
||||
//
|
||||
|
||||
// Package mock_acl is a generated GoMock package.
|
||||
package mock_acl
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
app "github.com/anyproto/any-sync/app"
|
||||
list "github.com/anyproto/any-sync/commonspace/object/acl/list"
|
||||
consensusproto "github.com/anyproto/any-sync/consensus/consensusproto"
|
||||
crypto "github.com/anyproto/any-sync/util/crypto"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockAclService is a mock of AclService interface.
|
||||
type MockAclService struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAclServiceMockRecorder
|
||||
}
|
||||
|
||||
// MockAclServiceMockRecorder is the mock recorder for MockAclService.
|
||||
type MockAclServiceMockRecorder struct {
|
||||
mock *MockAclService
|
||||
}
|
||||
|
||||
// NewMockAclService creates a new mock instance.
|
||||
func NewMockAclService(ctrl *gomock.Controller) *MockAclService {
|
||||
mock := &MockAclService{ctrl: ctrl}
|
||||
mock.recorder = &MockAclServiceMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAclService) EXPECT() *MockAclServiceMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AddRecord mocks base method.
|
||||
func (m *MockAclService) AddRecord(arg0 context.Context, arg1 string, arg2 *consensusproto.RawRecord) (*consensusproto.RawRecordWithId, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddRecord", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(*consensusproto.RawRecordWithId)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AddRecord indicates an expected call of AddRecord.
|
||||
func (mr *MockAclServiceMockRecorder) AddRecord(arg0, arg1, arg2 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRecord", reflect.TypeOf((*MockAclService)(nil).AddRecord), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Close mocks base method.
|
||||
func (m *MockAclService) Close(arg0 context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Close", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Close indicates an expected call of Close.
|
||||
func (mr *MockAclServiceMockRecorder) Close(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockAclService)(nil).Close), arg0)
|
||||
}
|
||||
|
||||
// Init mocks base method.
|
||||
func (m *MockAclService) Init(arg0 *app.App) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Init", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Init indicates an expected call of Init.
|
||||
func (mr *MockAclServiceMockRecorder) Init(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockAclService)(nil).Init), arg0)
|
||||
}
|
||||
|
||||
// Name mocks base method.
|
||||
func (m *MockAclService) Name() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Name")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Name indicates an expected call of Name.
|
||||
func (mr *MockAclServiceMockRecorder) Name() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockAclService)(nil).Name))
|
||||
}
|
||||
|
||||
// OwnerPubKey mocks base method.
|
||||
func (m *MockAclService) OwnerPubKey(arg0 context.Context, arg1 string) (crypto.PubKey, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OwnerPubKey", arg0, arg1)
|
||||
ret0, _ := ret[0].(crypto.PubKey)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// OwnerPubKey indicates an expected call of OwnerPubKey.
|
||||
func (mr *MockAclServiceMockRecorder) OwnerPubKey(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OwnerPubKey", reflect.TypeOf((*MockAclService)(nil).OwnerPubKey), arg0, arg1)
|
||||
}
|
||||
|
||||
// Permissions mocks base method.
|
||||
func (m *MockAclService) Permissions(arg0 context.Context, arg1 crypto.PubKey, arg2 string) (list.AclPermissions, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Permissions", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(list.AclPermissions)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Permissions indicates an expected call of Permissions.
|
||||
func (mr *MockAclServiceMockRecorder) Permissions(arg0, arg1, arg2 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Permissions", reflect.TypeOf((*MockAclService)(nil).Permissions), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// RecordsAfter mocks base method.
|
||||
func (m *MockAclService) RecordsAfter(arg0 context.Context, arg1, arg2 string) ([]*consensusproto.RawRecordWithId, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RecordsAfter", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]*consensusproto.RawRecordWithId)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RecordsAfter indicates an expected call of RecordsAfter.
|
||||
func (mr *MockAclServiceMockRecorder) RecordsAfter(arg0, arg1, arg2 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordsAfter", reflect.TypeOf((*MockAclService)(nil).RecordsAfter), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Run mocks base method.
|
||||
func (m *MockAclService) Run(arg0 context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Run", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Run indicates an expected call of Run.
|
||||
func (mr *MockAclServiceMockRecorder) Run(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockAclService)(nil).Run), arg0)
|
||||
}
|
|
@ -34,6 +34,7 @@ var (
|
|||
ErrIncorrectRoot = errors.New("incorrect root")
|
||||
ErrIncorrectRecordSequence = errors.New("incorrect prev id of a record")
|
||||
ErrMetadataTooLarge = errors.New("metadata size too large")
|
||||
ErrOwnerNotFound = errors.New("owner not found")
|
||||
)
|
||||
|
||||
const MaxMetadataLen = 1024
|
||||
|
@ -844,6 +845,15 @@ func (st *AclState) LastRecordId() string {
|
|||
return st.lastRecordId
|
||||
}
|
||||
|
||||
func (st *AclState) OwnerPubKey() (ownerIdentity crypto.PubKey, err error) {
|
||||
for _, aState := range st.accountStates {
|
||||
if aState.Permissions.IsOwner() {
|
||||
return aState.PubKey, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrOwnerNotFound
|
||||
}
|
||||
|
||||
func (st *AclState) deriveKey() (crypto.SymKey, error) {
|
||||
keyBytes, err := st.key.Raw()
|
||||
if err != nil {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
||||
|
@ -395,3 +396,10 @@ func TestAclList_RequestRemove(t *testing.T) {
|
|||
require.Nil(t, accountState().keys[removeRec.Id].ReadKey)
|
||||
require.NotEmpty(t, accountState().keys[fx.ownerAcl.Id()])
|
||||
}
|
||||
|
||||
func TestAclState_OwnerPubKey(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
pubKey, err := fx.ownerAcl.AclState().OwnerPubKey()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, fx.ownerKeys.SignKey.GetPublic().Account(), pubKey.Account())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue