1
0
Fork 0
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:
Sergey Cherepanov 2024-03-11 16:04:14 +01:00
parent 19798f2295
commit 151dd9508d
No known key found for this signature in database
GPG key ID: 87F8EDE8FBDF637C
5 changed files with 231 additions and 8 deletions

View file

@ -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 {

View file

@ -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
View 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)
}

View file

@ -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 {

View file

@ -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())
}