1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-08 05:47:07 +09:00

GO-3174 Major refactoring for tests

This commit is contained in:
mcrakhman 2024-04-07 20:44:39 +02:00
parent 8106a7f873
commit 9584bf73bf
No known key found for this signature in database
GPG key ID: DED12CFEF5B8396B
28 changed files with 1519 additions and 863 deletions

View file

@ -67,9 +67,10 @@ packages:
github.com/anyproto/anytype-heart/space/spacecore:
interfaces:
SpaceCoreService:
github.com/anyproto/anytype-heart/space/internal/techspace:
github.com/anyproto/anytype-heart/space/techspace:
interfaces:
TechSpace:
SpaceView:
github.com/anyproto/anytype-heart/space/spacefactory:
interfaces:
SpaceFactory:

View file

@ -14,24 +14,17 @@ import (
"github.com/anyproto/any-sync/coordinator/coordinatorclient"
"github.com/anyproto/any-sync/coordinator/coordinatorproto"
"github.com/anyproto/any-sync/util/crypto"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/types"
"github.com/ipfs/go-cid"
"github.com/mr-tron/base58/base58"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/anytype/account"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
"github.com/anyproto/anytype-heart/core/block/getblock"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/files/fileacl"
"github.com/anyproto/anytype-heart/core/invitestore"
"github.com/anyproto/anytype-heart/core/inviteservice"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space"
"github.com/anyproto/anytype-heart/space/clientspace"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
"github.com/anyproto/anytype-heart/util/pbtypes"
)
@ -65,10 +58,10 @@ type aclSpaceView interface {
type AclService interface {
app.Component
GenerateInvite(ctx context.Context, spaceId string) (*InviteInfo, error)
GenerateInvite(ctx context.Context, spaceId string) (inviteservice.InviteInfo, error)
RevokeInvite(ctx context.Context, spaceId string) error
GetCurrentInvite(spaceId string) (*InviteInfo, error)
ViewInvite(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (*InviteView, error)
GetCurrentInvite(ctx context.Context, spaceId string) (inviteservice.InviteInfo, error)
ViewInvite(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (inviteservice.InviteView, error)
Join(ctx context.Context, spaceId string, inviteCid cid.Cid, inviteFileKey crypto.SymKey) error
ApproveLeave(ctx context.Context, spaceId string, identities []crypto.PubKey) error
MakeShareable(ctx context.Context, spaceId string) error
@ -88,20 +81,15 @@ func New() AclService {
type aclService struct {
joiningClient aclclient.AclJoiningClient
spaceService space.Service
inviteService inviteservice.InviteService
accountService account.Service
coordClient coordinatorclient.CoordinatorClient
inviteStore invitestore.Service
fileAcl fileacl.Service
objectGetter getblock.ObjectGetter
}
func (a *aclService) Init(ap *app.App) (err error) {
a.joiningClient = app.MustComponent[aclclient.AclJoiningClient](ap)
a.spaceService = app.MustComponent[space.Service](ap)
a.accountService = app.MustComponent[account.Service](ap)
a.inviteStore = app.MustComponent[invitestore.Service](ap)
a.fileAcl = app.MustComponent[fileacl.Service](ap)
a.objectGetter = app.MustComponent[getblock.ObjectGetter](ap)
a.coordClient = app.MustComponent[coordinatorclient.CoordinatorClient](ap)
return nil
}
@ -178,11 +166,7 @@ func (a *aclService) RevokeInvite(ctx context.Context, spaceId string) error {
if err != nil {
return fmt.Errorf("%w, %w", ErrAclRequestFailed, err)
}
spaceView, err := a.spaceService.TechSpace().GetSpaceView(ctx, spaceId)
if err != nil {
return fmt.Errorf("get space view id: %w", err)
}
return a.removeExistingInviteFileInfo(ctx, spaceView)
return a.inviteService.RemoveExisting(ctx, spaceId)
}
func (a *aclService) ChangePermissions(ctx context.Context, spaceId string, perms []AccountPermissions) error {
@ -277,42 +261,34 @@ func (a *aclService) StopSharing(ctx context.Context, spaceId string) error {
if err != nil {
return err
}
spaceView, err := a.spaceService.TechSpace().GetSpaceView(ctx, spaceId)
if err != nil {
return err
}
spaceView.Lock()
localInfo := spaceView.GetLocalInfo()
spaceView.Unlock()
acl := removeSpace.CommonSpace().Acl()
acl.RLock()
isEmpty := aclIsEmpty(acl)
head := acl.Head().Id
acl.RUnlock()
if isEmpty && localInfo.GetShareableStatus() != spaceinfo.ShareableStatusShareable {
var localInfo spaceinfo.SpaceLocalInfo
err = a.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
localInfo = spaceView.GetLocalInfo()
return nil
}
})
acl := removeSpace.CommonSpace().Acl()
newPrivKey, _, err := crypto.GenerateRandomEd25519KeyPair()
if err != nil {
return err
}
if !isEmpty {
cl := removeSpace.CommonSpace().AclClient()
err = cl.StopSharing(ctx, list.ReadKeyChangePayload{
MetadataKey: newPrivKey,
ReadKey: crypto.NewAES(),
})
if err != nil {
return fmt.Errorf("%w, %w", ErrAclRequestFailed, err)
}
acl.RLock()
head = acl.Head().Id
acl.RUnlock()
cl := removeSpace.CommonSpace().AclClient()
err = cl.StopSharing(ctx, list.ReadKeyChangePayload{
MetadataKey: newPrivKey,
ReadKey: crypto.NewAES(),
})
if err != nil {
return fmt.Errorf("%w, %w", ErrAclRequestFailed, err)
}
err = a.removeExistingInviteFileInfo(ctx, spaceView)
acl.RLock()
head := acl.Head().Id
acl.RUnlock()
err = a.inviteService.RemoveExisting(ctx, spaceId)
if err != nil {
return fmt.Errorf("remove existing invite file info: %w", err)
}
if localInfo.GetShareableStatus() != spaceinfo.ShareableStatusShareable {
return nil
}
for {
err = a.coordClient.SpaceMakeUnshareable(ctx, spaceId, head)
if errors.Is(err, coordinatorproto.ErrAclHeadIsMissing) {
@ -330,7 +306,7 @@ func (a *aclService) StopSharing(ctx context.Context, spaceId string) error {
}
func (a *aclService) Join(ctx context.Context, spaceId string, inviteCid cid.Cid, inviteFileKey crypto.SymKey) error {
invitePayload, err := a.getInvitePayload(ctx, inviteCid, inviteFileKey)
invitePayload, err := a.inviteService.GetPayload(ctx, inviteCid, inviteFileKey)
if err != nil {
return fmt.Errorf("get invite payload: %w", err)
}
@ -363,55 +339,8 @@ func (a *aclService) Join(ctx context.Context, spaceId string, inviteCid cid.Cid
}})
}
type InviteView struct {
SpaceId string
SpaceName string
SpaceIconCid string
CreatorName string
}
func (a *aclService) ViewInvite(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (*InviteView, error) {
invitePayload, err := a.getInvitePayload(ctx, inviteCid, inviteFileKey)
if err != nil {
return nil, fmt.Errorf("get invite payload: %w", err)
}
return &InviteView{
SpaceId: invitePayload.SpaceId,
SpaceName: invitePayload.SpaceName,
SpaceIconCid: invitePayload.SpaceIconCid,
CreatorName: invitePayload.CreatorName,
}, nil
}
func (a *aclService) getInvitePayload(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (*model.InvitePayload, error) {
invite, err := a.inviteStore.GetInvite(ctx, inviteCid, inviteFileKey)
if err != nil {
return nil, fmt.Errorf("get invite: %w", err)
}
var invitePayload model.InvitePayload
err = proto.Unmarshal(invite.Payload, &invitePayload)
if err != nil {
return nil, fmt.Errorf("unmarshal invite payload: %w", err)
}
creatorIdentity, err := crypto.DecodeAccountAddress(invitePayload.CreatorIdentity)
if err != nil {
return nil, fmt.Errorf("decode creator identity: %w", err)
}
ok, err := creatorIdentity.Verify(invite.Payload, invite.Signature)
if err != nil {
return nil, fmt.Errorf("verify invite signature: %w", err)
}
if !ok {
return nil, ErrInviteBadSignature
}
err = a.fileAcl.StoreFileKeys(domain.FileId(invitePayload.SpaceIconCid), invitePayload.SpaceIconEncryptionKeys)
if err != nil {
return nil, fmt.Errorf("store icon keys: %w", err)
}
return &invitePayload, nil
func (a *aclService) ViewInvite(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (inviteservice.InviteView, error) {
return a.inviteService.View(ctx, inviteCid, inviteFileKey)
}
func (a *aclService) Accept(ctx context.Context, spaceId string, identity crypto.PubKey, permissions model.ParticipantPermissions) error {
@ -459,209 +388,29 @@ func (a *aclService) Accept(ctx context.Context, spaceId string, identity crypto
return nil
}
type InviteInfo struct {
InviteFileCid string
InviteFileKey string
func (a *aclService) GetCurrentInvite(ctx context.Context, spaceId string) (inviteservice.InviteInfo, error) {
return a.inviteService.GetCurrent(ctx, spaceId)
}
func (a *aclService) buildInvite(ctx context.Context, space clientspace.Space, inviteKey crypto.PrivKey) (*model.Invite, error) {
invitePayload, err := a.buildInvitePayload(ctx, space, inviteKey)
if err != nil {
return nil, fmt.Errorf("build invite payload: %w", err)
}
invitePayloadRaw, err := proto.Marshal(invitePayload)
if err != nil {
return nil, fmt.Errorf("marshal invite payload: %w", err)
}
invitePayloadSignature, err := a.accountService.SignData(invitePayloadRaw)
if err != nil {
return nil, fmt.Errorf("sign invite payload: %w", err)
}
return &model.Invite{
Payload: invitePayloadRaw,
Signature: invitePayloadSignature,
}, nil
}
func (a *aclService) buildInvitePayload(ctx context.Context, space clientspace.Space, inviteKey crypto.PrivKey) (*model.InvitePayload, error) {
profile, err := a.accountService.ProfileInfo()
if err != nil {
return nil, fmt.Errorf("get profile info: %w", err)
}
rawInviteKey, err := inviteKey.Marshall()
if err != nil {
return nil, fmt.Errorf("marshal invite priv key: %w", err)
}
invitePayload := &model.InvitePayload{
SpaceId: space.Id(),
CreatorIdentity: a.accountService.AccountID(),
CreatorName: profile.Name,
InviteKey: rawInviteKey,
}
err = space.Do(space.DerivedIDs().Workspace, func(sb smartblock.SmartBlock) error {
details := sb.Details()
invitePayload.SpaceName = pbtypes.GetString(details, bundle.RelationKeyName.String())
iconObjectId := pbtypes.GetString(details, bundle.RelationKeyIconImage.String())
if iconObjectId != "" {
iconCid, iconEncryptionKeys, err := a.fileAcl.GetInfoForFileSharing(ctx, iconObjectId)
if err == nil {
invitePayload.SpaceIconCid = iconCid
invitePayload.SpaceIconEncryptionKeys = iconEncryptionKeys
} else {
log.Error("get space icon info", zap.Error(err))
}
}
return nil
})
if err != nil {
return nil, err
}
return invitePayload, nil
}
type spaceViewObject interface {
SetInviteFileInfo(fileCid string, fileKey string) (err error)
}
func (a *aclService) getExistingInviteFileInfo(spaceViewId string) (fileCid string, fileKey string, err error) {
err = getblock.Do(a.objectGetter, spaceViewId, func(sb smartblock.SmartBlock) error {
details := sb.Details()
fileCid = pbtypes.GetString(details, bundle.RelationKeySpaceInviteFileCid.String())
fileKey = pbtypes.GetString(details, bundle.RelationKeySpaceInviteFileKey.String())
return nil
})
return
}
func (a *aclService) removeExistingInviteFileInfo(ctx context.Context, spaceView aclSpaceView) (err error) {
fileCid, err := spaceView.RemoveExistingInvite()
if err != nil {
return fmt.Errorf("remove existing invite: %w", err)
}
cId, err := cid.Decode(fileCid)
if err != nil {
return fmt.Errorf("decode file cid: %w", err)
}
return a.inviteStore.RemoveInvite(ctx, cId)
}
func (a *aclService) GetCurrentInvite(spaceId string) (*InviteInfo, error) {
spaceViewId, err := a.spaceService.SpaceViewId(spaceId)
if err != nil {
return nil, fmt.Errorf("get space view id: %w", err)
}
fileCid, fileKey, err := a.getExistingInviteFileInfo(spaceViewId)
if err != nil {
return nil, fmt.Errorf("get existing invite file info: %w", err)
}
if fileCid == "" {
return nil, ErrInviteNotExists
}
return &InviteInfo{
InviteFileCid: fileCid,
InviteFileKey: fileKey,
}, nil
}
func (a *aclService) GenerateInvite(ctx context.Context, spaceId string) (result *InviteInfo, err error) {
func (a *aclService) GenerateInvite(ctx context.Context, spaceId string) (result inviteservice.InviteInfo, err error) {
if spaceId == a.accountService.PersonalSpaceID() {
return nil, ErrPersonalSpace
err = ErrPersonalSpace
return
}
spaceViewId, err := a.spaceService.SpaceViewId(spaceId)
if err != nil {
return nil, fmt.Errorf("get space view id: %w", err)
current, err := a.inviteService.GetCurrent(ctx, spaceId)
if err == nil {
return current, nil
}
fileCid, fileKey, err := a.getExistingInviteFileInfo(spaceViewId)
if err != nil {
return nil, fmt.Errorf("get existing invite file info: %w", err)
}
if fileCid != "" {
return &InviteInfo{
InviteFileCid: fileCid,
InviteFileKey: fileKey,
}, nil
}
acceptSpace, err := a.spaceService.Get(ctx, spaceId)
if err != nil {
return nil, err
return
}
aclClient := acceptSpace.CommonSpace().AclClient()
res, err := aclClient.GenerateInvite()
if err != nil {
return nil, err
return
}
invite, err := a.buildInvite(ctx, acceptSpace, res.InviteKey)
if err != nil {
return nil, fmt.Errorf("build invite: %w", err)
}
inviteFileCid, inviteFileKey, err := a.inviteStore.StoreInvite(ctx, invite)
if err != nil {
return nil, fmt.Errorf("store invite in ipfs: %w", err)
}
removeInviteFile := func() {
err := a.inviteStore.RemoveInvite(ctx, inviteFileCid)
if err != nil {
log.Error("remove invite file", zap.Error(err))
}
}
inviteFileKeyRaw, err := EncodeKeyToBase58(inviteFileKey)
if err != nil {
removeInviteFile()
return nil, fmt.Errorf("encode invite file key: %w", err)
}
err = getblock.Do(a.objectGetter, spaceViewId, func(sb smartblock.SmartBlock) error {
view, ok := sb.(spaceViewObject)
if !ok {
return fmt.Errorf("space view object is not implemented")
}
return view.SetInviteFileInfo(inviteFileCid.String(), inviteFileKeyRaw)
return a.inviteService.Generate(ctx, spaceId, res.InviteKey, func() error {
return aclClient.AddRecord(ctx, res.InviteRec)
})
if err != nil {
removeInviteFile()
return nil, fmt.Errorf("set invite file info: %w", err)
}
err = aclClient.AddRecord(ctx, res.InviteRec)
if err != nil {
removeInviteFile()
return nil, fmt.Errorf("%w, %w", ErrAclRequestFailed, err)
}
return &InviteInfo{
InviteFileCid: inviteFileCid.String(),
InviteFileKey: inviteFileKeyRaw,
}, err
}
func EncodeKeyToBase58(key crypto.SymKey) (string, error) {
raw, err := key.Raw()
if err != nil {
return "", err
}
return base58.Encode(raw), nil
}
func DecodeKeyFromBase58(rawString string) (crypto.SymKey, error) {
raw, err := base58.Decode(rawString)
if err != nil {
return nil, err
}
return crypto.UnmarshallAESKey(raw)
}
func aclIsEmpty(acl list.AclList) bool {
isEmpty := len(acl.AclState().Invites()) == 0
if !isEmpty {
return false
}
users := 0
for _, acc := range acl.AclState().CurrentAccounts() {
if !acc.Permissions.NoPermissions() {
users++
}
}
return users == 1
}

View file

@ -3,10 +3,13 @@ package editor
import (
"time"
"github.com/gogo/protobuf/types"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
"github.com/anyproto/anytype-heart/core/block/editor/template"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/util/pbtypes"
)
@ -45,6 +48,53 @@ func (p *participant) Init(ctx *smartblock.InitContext) (err error) {
return nil
}
func (p *participant) ModifyOwnerDetails(profileDetails *types.Struct, aclInfo spaceinfo.ParticipantAclInfo) (err error) {
details := buildParticipantDetails(aclInfo.Id, aclInfo.SpaceId, aclInfo.Identity, aclInfo.Permissions, aclInfo.Status)
details.Fields[bundle.RelationKeyName.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyName.String()))
details.Fields[bundle.RelationKeyDescription.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyDescription.String()))
details.Fields[bundle.RelationKeyIconImage.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyIconImage.String()))
details.Fields[bundle.RelationKeyIdentityProfileLink.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyId.String()))
details.Fields[bundle.RelationKeyGlobalName.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyGlobalName.String()))
return p.modifyDetails(details)
}
func (p *participant) ModifyIdentityDetails(profile *model.IdentityProfile) (err error) {
details := &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyName.String(): pbtypes.String(profile.Name),
bundle.RelationKeyDescription.String(): pbtypes.String(profile.Description),
bundle.RelationKeyIconImage.String(): pbtypes.String(profile.IconCid),
bundle.RelationKeyGlobalName.String(): pbtypes.String(profile.GlobalName),
}}
return p.modifyDetails(details)
}
func (p *participant) ModifyParticipantAclState(accState spaceinfo.ParticipantAclInfo) (err error) {
details := buildParticipantDetails(accState.Id, accState.SpaceId, accState.Identity, accState.Permissions, accState.Status)
return p.modifyDetails(details)
}
func (p *participant) TryClose(objectTTL time.Duration) (bool, error) {
return false, nil
}
func (p *participant) modifyDetails(newDetails *types.Struct) (err error) {
return p.Apply(p.NewState().SetDetails(pbtypes.StructMerge(p.CombinedDetails(), newDetails, false)))
}
func buildParticipantDetails(
id string,
spaceId string,
identity string,
permissions model.ParticipantPermissions,
status model.ParticipantStatus,
) *types.Struct {
return &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(id),
bundle.RelationKeyIdentity.String(): pbtypes.String(identity),
bundle.RelationKeySpaceId.String(): pbtypes.String(spaceId),
bundle.RelationKeyLastModifiedBy.String(): pbtypes.String(id),
bundle.RelationKeyParticipantPermissions.String(): pbtypes.Int64(int64(permissions)),
bundle.RelationKeyParticipantStatus.String(): pbtypes.Int64(int64(status)),
bundle.RelationKeyIsHiddenDiscovery.String(): pbtypes.Bool(status != model.ParticipantStatus_Active),
}}
}

View file

@ -103,6 +103,21 @@ func (s *SpaceView) initTemplate(st *state.State) {
)
}
func (s *SpaceView) GetExistingInviteInfo() (fileCid string, fileKey string) {
details := s.CombinedDetails()
fileCid = pbtypes.GetString(details, bundle.RelationKeySpaceInviteFileCid.String())
fileKey = pbtypes.GetString(details, bundle.RelationKeySpaceInviteFileKey.String())
return
}
func (s *SpaceView) RemoveExistingInviteInfo() (fileCid string, err error) {
details := s.Details()
fileCid = pbtypes.GetString(details, bundle.RelationKeySpaceInviteFileCid.String())
newState := s.NewState()
newState.RemoveDetail(bundle.RelationKeySpaceInviteFileCid.String(), bundle.RelationKeySpaceInviteFileKey.String())
return fileCid, s.Apply(newState)
}
func (s *SpaceView) TryClose(objectTTL time.Duration) (res bool, err error) {
return false, nil
}
@ -162,7 +177,7 @@ func (s *SpaceView) SetInviteFileInfo(fileCid string, fileKey string) (err error
}
func (s *SpaceView) afterApply(info smartblock.ApplyInfo) (err error) {
s.spaceService.OnViewUpdated(s.getStatePersistentInfo(info.State))
s.spaceService.OnViewUpdated(s.getSpacePersistentInfo(info.State))
return nil
}
@ -196,7 +211,7 @@ func (s *SpaceView) targetSpaceID() (id string, err error) {
return changePayload.Key, nil
}
func (s *SpaceView) getStatePersistentInfo(st *state.State) (info spaceinfo.SpacePersistentInfo) {
func (s *SpaceView) getSpacePersistentInfo(st *state.State) (info spaceinfo.SpacePersistentInfo) {
details := st.CombinedDetails()
spaceInfo := spaceinfo.NewSpacePersistentInfo(pbtypes.GetString(details, bundle.RelationKeyTargetSpaceId.String()))
spaceInfo.SetAccountStatus(spaceinfo.AccountStatus(pbtypes.GetInt64(details, bundle.RelationKeySpaceAccountStatus.String()))).
@ -213,6 +228,13 @@ var workspaceKeysToCopy = []string{
bundle.RelationKeyCreatedDate.String(),
}
func (s *SpaceView) GetSpaceDescription() (data spaceinfo.SpaceDescription) {
details := s.CombinedDetails()
data.Name = pbtypes.GetString(details, bundle.RelationKeyName.String())
data.IconImage = pbtypes.GetString(details, bundle.RelationKeyIconImage.String())
return
}
func (s *SpaceView) SetSpaceData(details *types.Struct) error {
st := s.NewState()
var changed bool

View file

@ -0,0 +1,275 @@
package inviteservice
import (
"context"
"errors"
"fmt"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/util/crypto"
"github.com/gogo/protobuf/proto"
"github.com/ipfs/go-cid"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/anytype/account"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/core/files/fileacl"
"github.com/anyproto/anytype-heart/core/invitestore"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
"github.com/anyproto/anytype-heart/util/encode"
)
var (
ErrInviteNotExists = errors.New("invite not exists")
ErrInviteBadSignature = errors.New("invite bad signature")
ErrPersonalSpace = errors.New("personal space")
)
type InviteInfo struct {
InviteFileCid string
InviteFileKey string
}
const CName = "common.core.inviteservice"
var log = logger.NewNamed(CName)
type InviteView struct {
SpaceId string
SpaceName string
SpaceIconCid string
CreatorName string
}
type InviteService interface {
app.ComponentRunnable
GetPayload(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (*model.InvitePayload, error)
View(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (InviteView, error)
RemoveExisting(ctx context.Context, spaceId string) error
Generate(ctx context.Context, spaceId string, inviteKey crypto.PrivKey, sendInvite func() error) (InviteInfo, error)
GetCurrent(ctx context.Context, spaceId string) (InviteInfo, error)
}
var _ InviteService = (*inviteService)(nil)
type inviteService struct {
inviteStore invitestore.Service
fileAcl fileacl.Service
accountService account.Service
spaceService space.Service
}
func New() InviteService {
return &inviteService{}
}
func (i *inviteService) Init(a *app.App) (err error) {
i.inviteStore = app.MustComponent[invitestore.Service](a)
i.fileAcl = app.MustComponent[fileacl.Service](a)
i.accountService = app.MustComponent[account.Service](a)
i.spaceService = app.MustComponent[space.Service](a)
return
}
func (i *inviteService) Name() (name string) {
return CName
}
func (i *inviteService) Run(ctx context.Context) (err error) {
return
}
func (i *inviteService) Close(ctx context.Context) (err error) {
return
}
func (i *inviteService) View(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (InviteView, error) {
invitePayload, err := i.GetPayload(ctx, inviteCid, inviteFileKey)
if err != nil {
return InviteView{}, fmt.Errorf("get invite payload: %w", err)
}
return InviteView{
SpaceId: invitePayload.SpaceId,
SpaceName: invitePayload.SpaceName,
SpaceIconCid: invitePayload.SpaceIconCid,
CreatorName: invitePayload.CreatorName,
}, nil
}
func (i *inviteService) GetCurrent(ctx context.Context, spaceId string) (info InviteInfo, err error) {
var (
fileCid, fileKey string
)
err = i.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
fileCid, fileKey = spaceView.GetExistingInviteInfo()
return nil
})
if err != nil {
err = fmt.Errorf("get existing invite file info: %w", err)
return
}
if fileCid == "" {
err = ErrInviteNotExists
return
}
info.InviteFileCid = fileCid
info.InviteFileKey = fileKey
return
}
func (i *inviteService) RemoveExisting(ctx context.Context, spaceId string) (err error) {
var fileCid string
err = i.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
fileCid, err = spaceView.RemoveExistingInviteInfo()
return err
})
if err != nil {
return fmt.Errorf("remove existing invite: %w", err)
}
invCid, err := cid.Decode(fileCid)
if err != nil {
return fmt.Errorf("decode file cid: %w", err)
}
return i.inviteStore.RemoveInvite(ctx, invCid)
}
func (i *inviteService) Generate(ctx context.Context, spaceId string, inviteKey crypto.PrivKey, sendInvite func() error) (result InviteInfo, err error) {
if spaceId == i.accountService.PersonalSpaceID() {
return InviteInfo{}, ErrPersonalSpace
}
var fileCid, fileKey string
err = i.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
fileCid, fileKey = spaceView.GetExistingInviteInfo()
return nil
})
if err != nil {
return InviteInfo{}, fmt.Errorf("get space view id: %w", err)
}
if fileCid != "" {
return InviteInfo{
InviteFileCid: fileCid,
InviteFileKey: fileKey,
}, nil
}
invite, err := i.buildInvite(ctx, spaceId, inviteKey)
if err != nil {
return InviteInfo{}, fmt.Errorf("build invite: %w", err)
}
inviteFileCid, inviteFileKey, err := i.inviteStore.StoreInvite(ctx, invite)
if err != nil {
return InviteInfo{}, fmt.Errorf("store invite in ipfs: %w", err)
}
removeInviteFile := func() {
err := i.inviteStore.RemoveInvite(ctx, inviteFileCid)
if err != nil {
log.Error("remove invite file", zap.Error(err))
}
}
inviteFileKeyRaw, err := encode.EncodeKeyToBase58(inviteFileKey)
if err != nil {
removeInviteFile()
return InviteInfo{}, fmt.Errorf("encode invite file key: %w", err)
}
err = i.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
return spaceView.SetInviteFileInfo(inviteFileCid.String(), inviteFileKeyRaw)
})
if err != nil {
removeInviteFile()
return InviteInfo{}, fmt.Errorf("set invite file info: %w", err)
}
err = sendInvite()
if err != nil {
_ = i.RemoveExisting(ctx, spaceId)
return InviteInfo{}, fmt.Errorf("failed to send invite: %w", err)
}
return InviteInfo{
InviteFileCid: inviteFileCid.String(),
InviteFileKey: inviteFileKeyRaw,
}, err
}
func (i *inviteService) buildInvite(ctx context.Context, spaceId string, inviteKey crypto.PrivKey) (*model.Invite, error) {
invitePayload, err := i.buildInvitePayload(ctx, spaceId, inviteKey)
if err != nil {
return nil, fmt.Errorf("build invite payload: %w", err)
}
invitePayloadRaw, err := proto.Marshal(invitePayload)
if err != nil {
return nil, fmt.Errorf("marshal invite payload: %w", err)
}
invitePayloadSignature, err := i.accountService.SignData(invitePayloadRaw)
if err != nil {
return nil, fmt.Errorf("sign invite payload: %w", err)
}
return &model.Invite{
Payload: invitePayloadRaw,
Signature: invitePayloadSignature,
}, nil
}
func (i *inviteService) buildInvitePayload(ctx context.Context, spaceId string, inviteKey crypto.PrivKey) (*model.InvitePayload, error) {
profile, err := i.accountService.ProfileInfo()
if err != nil {
return nil, fmt.Errorf("get profile info: %w", err)
}
rawInviteKey, err := inviteKey.Marshall()
if err != nil {
return nil, fmt.Errorf("marshal invite priv key: %w", err)
}
invitePayload := &model.InvitePayload{
SpaceId: spaceId,
CreatorIdentity: i.accountService.AccountID(),
CreatorName: profile.Name,
InviteKey: rawInviteKey,
}
var description spaceinfo.SpaceDescription
err = i.spaceService.TechSpace().DoSpaceView(ctx, spaceId, func(spaceView techspace.SpaceView) error {
description = spaceView.GetSpaceDescription()
return nil
})
if err != nil {
return nil, fmt.Errorf("get space description: %w", err)
}
if description.IconImage != "" {
iconCid, iconEncryptionKeys, err := i.fileAcl.GetInfoForFileSharing(ctx, description.IconImage)
if err == nil {
invitePayload.SpaceIconCid = iconCid
invitePayload.SpaceIconEncryptionKeys = iconEncryptionKeys
} else {
log.Error("get space icon info", zap.Error(err))
}
}
return invitePayload, nil
}
func (i *inviteService) GetPayload(ctx context.Context, inviteCid cid.Cid, inviteFileKey crypto.SymKey) (*model.InvitePayload, error) {
invite, err := i.inviteStore.GetInvite(ctx, inviteCid, inviteFileKey)
if err != nil {
return nil, fmt.Errorf("get invite: %w", err)
}
var invitePayload model.InvitePayload
err = proto.Unmarshal(invite.Payload, &invitePayload)
if err != nil {
return nil, fmt.Errorf("unmarshal invite payload: %w", err)
}
creatorIdentity, err := crypto.DecodeAccountAddress(invitePayload.CreatorIdentity)
if err != nil {
return nil, fmt.Errorf("decode creator identity: %w", err)
}
ok, err := creatorIdentity.Verify(invite.Payload, invite.Signature)
if err != nil {
return nil, fmt.Errorf("verify invite signature: %w", err)
}
if !ok {
return nil, ErrInviteBadSignature
}
err = i.fileAcl.StoreFileKeys(domain.FileId(invitePayload.SpaceIconCid), invitePayload.SpaceIconEncryptionKeys)
if err != nil {
return nil, fmt.Errorf("store icon keys: %w", err)
}
return &invitePayload, nil
}

View file

@ -11,9 +11,11 @@ import (
"github.com/ipfs/go-cid"
"github.com/anyproto/anytype-heart/core/acl"
"github.com/anyproto/anytype-heart/core/inviteservice"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space"
"github.com/anyproto/anytype-heart/util/encode"
)
func (mw *Middleware) SpaceDelete(cctx context.Context, req *pb.RpcSpaceDeleteRequest) *pb.RpcSpaceDeleteResponse {
@ -39,6 +41,26 @@ func (mw *Middleware) SpaceDelete(cctx context.Context, req *pb.RpcSpaceDeleteRe
}
}
func (mw *Middleware) SpaceMakeShareable(cctx context.Context, req *pb.RpcSpaceMakeShareableRequest) *pb.RpcSpaceMakeShareableResponse {
aclService := getService[acl.AclService](mw)
err := aclService.MakeShareable(cctx, req.SpaceId)
if err != nil {
code := mapErrorCode(err,
errToCode(space.ErrSpaceDeleted, pb.RpcSpaceMakeShareableResponseError_SPACE_IS_DELETED),
errToCode(space.ErrSpaceNotExists, pb.RpcSpaceMakeShareableResponseError_NO_SUCH_SPACE),
errToCode(acl.ErrPersonalSpace, pb.RpcSpaceMakeShareableResponseError_BAD_INPUT),
errToCode(acl.ErrAclRequestFailed, pb.RpcSpaceMakeShareableResponseError_REQUEST_FAILED),
)
return &pb.RpcSpaceMakeShareableResponse{
Error: &pb.RpcSpaceMakeShareableResponseError{
Code: code,
Description: getErrorDescription(err),
},
}
}
return &pb.RpcSpaceMakeShareableResponse{}
}
func (mw *Middleware) SpaceInviteGenerate(cctx context.Context, req *pb.RpcSpaceInviteGenerateRequest) *pb.RpcSpaceInviteGenerateResponse {
aclService := getService[acl.AclService](mw)
inviteInfo, err := aclService.GenerateInvite(cctx, req.SpaceId)
@ -64,7 +86,7 @@ func (mw *Middleware) SpaceInviteGenerate(cctx context.Context, req *pb.RpcSpace
func (mw *Middleware) SpaceInviteGetCurrent(cctx context.Context, req *pb.RpcSpaceInviteGetCurrentRequest) *pb.RpcSpaceInviteGetCurrentResponse {
aclService := getService[acl.AclService](mw)
inviteInfo, err := aclService.GetCurrentInvite(req.SpaceId)
inviteInfo, err := aclService.GetCurrentInvite(cctx, req.SpaceId)
if err != nil {
code := mapErrorCode(err,
errToCode(acl.ErrInviteNotExists, pb.RpcSpaceInviteGetCurrentResponseError_NO_ACTIVE_INVITE),
@ -120,14 +142,14 @@ func (mw *Middleware) SpaceInviteView(cctx context.Context, req *pb.RpcSpaceInvi
}
}
func viewInvite(ctx context.Context, aclService acl.AclService, req *pb.RpcSpaceInviteViewRequest) (*acl.InviteView, error) {
inviteFileKey, err := acl.DecodeKeyFromBase58(req.InviteFileKey)
func viewInvite(ctx context.Context, aclService acl.AclService, req *pb.RpcSpaceInviteViewRequest) (inviteservice.InviteView, error) {
inviteFileKey, err := encode.DecodeKeyFromBase58(req.InviteFileKey)
if err != nil {
return nil, fmt.Errorf("decode key: %w", err)
return inviteservice.InviteView{}, fmt.Errorf("decode key: %w", err)
}
inviteCid, err := cid.Decode(req.InviteCid)
if err != nil {
return nil, err
return inviteservice.InviteView{}, err
}
return aclService.ViewInvite(ctx, inviteCid, inviteFileKey)
}
@ -281,7 +303,7 @@ func (mw *Middleware) SpaceLeaveApprove(cctx context.Context, req *pb.RpcSpaceLe
}
func join(ctx context.Context, aclService acl.AclService, req *pb.RpcSpaceJoinRequest) (err error) {
inviteFileKey, err := acl.DecodeKeyFromBase58(req.InviteFileKey)
inviteFileKey, err := encode.DecodeKeyFromBase58(req.InviteFileKey)
if err != nil {
return
}

2
go.mod
View file

@ -7,7 +7,7 @@ require (
github.com/PuerkitoBio/goquery v1.9.1
github.com/VividCortex/ewma v1.2.0
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
github.com/anyproto/any-sync v0.4.0
github.com/anyproto/any-sync v0.4.1-0.20240407113735-3d52c4c395f5
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
github.com/avast/retry-go/v4 v4.5.1

19
go.sum
View file

@ -89,10 +89,8 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-sync v0.3.36-0.20240402120641-e2866e9340d6 h1:6no9+otZ5lT0gZ5zz+3Rh42FeqTR+YZx6ZY8I8sbQKs=
github.com/anyproto/any-sync v0.3.36-0.20240402120641-e2866e9340d6/go.mod h1:rIv4hBJm1vHm2UdnWdBCYQzTtVK5utN7KkuKeMkLJnc=
github.com/anyproto/any-sync v0.4.0 h1:EF9tjSd6er3zpuoO5gJhKuF65sx7YSSJjEvrWqVUZdI=
github.com/anyproto/any-sync v0.4.0/go.mod h1:LclTfV2oKjwGqeMzWkRglivCg8+NmcDHZXeozyHho6w=
github.com/anyproto/any-sync v0.4.1-0.20240407113735-3d52c4c395f5 h1:soaU7D5l7acQE0Z/xfjDshxPAXjeQtOaR7ZyM6XH8Q8=
github.com/anyproto/any-sync v0.4.1-0.20240407113735-3d52c4c395f5/go.mod h1:LclTfV2oKjwGqeMzWkRglivCg8+NmcDHZXeozyHho6w=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580/go.mod h1:T/uWAYxrXdaXw64ihI++9RMbKTCpKd/yE9+saARew7k=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
@ -385,8 +383,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@ -522,8 +518,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY=
github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@ -1165,8 +1159,6 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -1552,8 +1544,6 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
@ -1588,8 +1578,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1868,8 +1856,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -10,7 +10,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/space/internal/techspace"
"github.com/anyproto/anytype-heart/space/techspace"
)
type TechSpace struct {

View file

@ -2,29 +2,21 @@ package aclobjectmanager
import (
"context"
"sync"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/debugstat"
"github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/commonspace"
"github.com/anyproto/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anyproto/any-sync/commonspace/object/acl/list"
"github.com/anyproto/any-sync/util/crypto"
"github.com/anyproto/any-sync/util/crypto/cryptoproto"
"github.com/gogo/protobuf/types"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space/clientspace"
"github.com/anyproto/anytype-heart/space/internal/components/aclnotifications"
"github.com/anyproto/anytype-heart/space/internal/components/dependencies"
"github.com/anyproto/anytype-heart/space/internal/components/participantwatcher"
"github.com/anyproto/anytype-heart/space/internal/components/spaceloader"
"github.com/anyproto/anytype-heart/space/internal/components/spacestatus"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/util/pbtypes"
)
const CName = "common.components.aclobjectmanager"
@ -51,15 +43,13 @@ type aclObjectManager struct {
loadErr error
spaceLoader spaceloader.SpaceLoader
status spacestatus.SpaceStatus
modifier dependencies.DetailsModifier
identityService dependencies.IdentityService
indexer dependencies.SpaceIndexer
statService debugstat.StatService
started bool
notificationService aclnotifications.AclNotification
participantWatcher participantwatcher.ParticipantWatcher
ownerMetadata []byte
mx sync.Mutex
lastIndexed string
addedParticipants map[string]struct{}
}
@ -93,10 +83,9 @@ func (a *aclObjectManager) UpdateAcl(aclList list.AclList) {
func (a *aclObjectManager) Init(ap *app.App) (err error) {
a.spaceLoader = ap.MustComponent(spaceloader.CName).(spaceloader.SpaceLoader)
a.modifier = app.MustComponent[dependencies.DetailsModifier](ap)
a.identityService = app.MustComponent[dependencies.IdentityService](ap)
a.indexer = app.MustComponent[dependencies.SpaceIndexer](ap)
a.status = app.MustComponent[spacestatus.SpaceStatus](ap)
a.participantWatcher = app.MustComponent[participantwatcher.ParticipantWatcher](ap)
a.notificationService = app.MustComponent[aclnotifications.AclNotification](ap)
a.statService, _ = ap.Component(debugstat.CName).(debugstat.StatService)
if a.statService == nil {
@ -113,7 +102,7 @@ func (a *aclObjectManager) Name() (name string) {
}
func (a *aclObjectManager) Run(ctx context.Context) (err error) {
err = a.clearAclIndexes()
err = a.indexer.RemoveAclIndexes(a.status.SpaceId())
if err != nil {
return
}
@ -130,7 +119,6 @@ func (a *aclObjectManager) Close(ctx context.Context) (err error) {
}
a.cancel()
<-a.wait
a.identityService.UnregisterIdentitiesInSpace(a.status.SpaceId())
a.statService.RemoveProvider(a)
return
}
@ -152,7 +140,7 @@ func (a *aclObjectManager) process() {
break
}
err := a.initAndRegisterMyIdentity(a.ctx)
err := a.participantWatcher.RegisterOwnerIdentity(a.ctx, a.sp)
if err != nil {
log.Error("init my identity", zap.Error(err))
}
@ -167,195 +155,63 @@ func (a *aclObjectManager) process() {
}
}
func (a *aclObjectManager) sendNotifications(common commonspace.Space) {
permissions := common.Acl().AclState().Permissions(common.Acl().AclState().AccountKey().GetPublic())
a.notificationService.AddRecords(common.Acl().(list.AclList), permissions, a.sp.Id(), spaceinfo.AccountStatusActive)
}
func (a *aclObjectManager) initAndRegisterMyIdentity(ctx context.Context) error {
myIdentity, metadataKey, profileDetails := a.identityService.GetMyProfileDetails()
id := domain.NewParticipantId(a.sp.Id(), myIdentity)
_, err := a.sp.GetObject(ctx, id)
if err != nil {
return err
}
details := buildParticipantDetails(id, a.sp.Id(), myIdentity, model.ParticipantPermissions_Owner, model.ParticipantStatus_Active)
details.Fields[bundle.RelationKeyName.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyName.String()))
details.Fields[bundle.RelationKeyDescription.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyDescription.String()))
details.Fields[bundle.RelationKeyIconImage.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyIconImage.String()))
details.Fields[bundle.RelationKeyIdentityProfileLink.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyId.String()))
details.Fields[bundle.RelationKeyGlobalName.String()] = pbtypes.String(pbtypes.GetString(profileDetails, bundle.RelationKeyGlobalName.String()))
err = a.modifier.ModifyDetails(id, func(current *types.Struct) (*types.Struct, error) {
return pbtypes.StructMerge(current, details, false), nil
})
if err != nil {
return err
}
err = a.identityService.RegisterIdentity(a.sp.Id(), myIdentity, metadataKey,
func(identity string, profile *model.IdentityProfile) {
err := a.updateParticipantFromIdentity(a.ctx, identity, profile)
if err != nil {
log.Error("error updating participant from identity", zap.Error(err))
}
},
)
if err != nil {
return err
}
a.mx.Lock()
a.addedParticipants[myIdentity] = struct{}{}
a.mx.Unlock()
return nil
}
func (a *aclObjectManager) clearAclIndexes() (err error) {
return a.indexer.RemoveAclIndexes(a.status.SpaceId())
}
func (a *aclObjectManager) processAcl() (err error) {
common := a.sp.CommonSpace()
a.mx.Lock()
var (
common = a.sp.CommonSpace()
acl = common.Acl()
aclState = acl.AclState()
)
defer func() {
if err == nil {
permissions := aclState.Permissions(aclState.AccountKey().GetPublic())
a.notificationService.AddRecords(acl, permissions, common.Id(), spaceinfo.AccountStatusActive)
}
}()
lastIndexed := a.lastIndexed
a.mx.Unlock()
if lastIndexed == common.Acl().Head().Id {
a.mx.Lock()
a.sendNotifications(common)
a.mx.Unlock()
return nil
if lastIndexed == acl.Head().Id {
return
}
decrypt := func(key crypto.PubKey) ([]byte, error) {
if a.ownerMetadata != nil {
return a.ownerMetadata, nil
}
return common.Acl().AclState().GetMetadata(key, true)
return aclState.GetMetadata(key, true)
}
states := common.Acl().AclState().CurrentAccounts()
states := aclState.CurrentAccounts()
// decrypt all metadata
states, err = decryptAll(states, decrypt)
if err != nil {
return
}
a.mx.Lock()
defer a.mx.Unlock()
aclHeadId := a.status.GetLatestAclHeadId()
var upToDate bool
if aclHeadId != "" {
_, err := common.Acl().Get(aclHeadId)
if err == nil {
upToDate = true
}
} else {
upToDate = true
}
err = a.processStates(states, upToDate, common.Acl().AclState().Identity())
statusAclHeadId := a.status.GetLatestAclHeadId()
upToDate := statusAclHeadId == "" || acl.HasHead(statusAclHeadId)
err = a.processStates(states, upToDate, aclState.Identity())
if err != nil {
return
}
a.lastIndexed = common.Acl().Head().Id
a.sendNotifications(common)
err = a.status.SetAclIsEmpty(aclState.IsEmpty())
if err != nil {
return
}
a.lastIndexed = acl.Head().Id
return
}
func (a *aclObjectManager) processStates(states []list.AccountState, upToDate bool, myIdentity crypto.PubKey) (err error) {
var numActiveUsers int
for _, state := range states {
if state.Permissions.NoPermissions() && state.PubKey.Equals(myIdentity) && upToDate {
return a.status.SetPersistentStatus(spaceinfo.AccountStatusRemoving)
}
if !state.Permissions.NoPermissions() {
numActiveUsers++
}
err := a.updateParticipantFromAclState(a.ctx, state)
err := a.participantWatcher.UpdateParticipantFromAclState(a.ctx, a.sp, state)
if err != nil {
return err
}
key, err := getSymKey(state.RequestMetadata)
err = a.participantWatcher.RegisterIdentity(a.ctx, a.sp, state)
if err != nil {
return err
}
accKey := state.PubKey.Account()
if _, exists := a.addedParticipants[state.PubKey.Account()]; exists {
continue
}
err = a.identityService.RegisterIdentity(a.sp.Id(), state.PubKey.Account(), key,
func(identity string, profile *model.IdentityProfile) {
err := a.updateParticipantFromIdentity(a.ctx, identity, profile)
if err != nil {
log.Error("error updating participant from identity", zap.Error(err))
}
},
)
if err != nil {
return err
}
a.addedParticipants[accKey] = struct{}{}
}
isEmpty := len(a.sp.CommonSpace().Acl().AclState().Invites()) == 0 && numActiveUsers == 1
return a.status.SetAclIsEmpty(isEmpty)
}
func (a *aclObjectManager) updateParticipantFromAclState(ctx context.Context, accState list.AccountState) (err error) {
id := domain.NewParticipantId(a.sp.Id(), accState.PubKey.Account())
_, err = a.sp.GetObject(ctx, id)
if err != nil {
return err
}
details := buildParticipantDetails(
id,
a.sp.Id(),
accState.PubKey.Account(),
convertPermissions(accState.Permissions),
convertStatus(accState.Status))
return a.modifier.ModifyDetails(id, func(current *types.Struct) (*types.Struct, error) {
return pbtypes.StructMerge(current, details, false), nil
})
}
func (a *aclObjectManager) updateParticipantFromIdentity(ctx context.Context, identity string, profile *model.IdentityProfile) (err error) {
id := domain.NewParticipantId(a.sp.Id(), identity)
_, err = a.sp.GetObject(ctx, id)
if err != nil {
return err
}
details := &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyName.String(): pbtypes.String(profile.Name),
bundle.RelationKeyDescription.String(): pbtypes.String(profile.Description),
bundle.RelationKeyIconImage.String(): pbtypes.String(profile.IconCid),
bundle.RelationKeyGlobalName.String(): pbtypes.String(profile.GlobalName),
}}
return a.modifier.ModifyDetails(id, func(current *types.Struct) (*types.Struct, error) {
return pbtypes.StructMerge(current, details, false), nil
})
}
func convertPermissions(permissions list.AclPermissions) model.ParticipantPermissions {
switch aclrecordproto.AclUserPermissions(permissions) {
case aclrecordproto.AclUserPermissions_Writer:
return model.ParticipantPermissions_Writer
case aclrecordproto.AclUserPermissions_Reader:
return model.ParticipantPermissions_Reader
case aclrecordproto.AclUserPermissions_Owner:
return model.ParticipantPermissions_Owner
}
return model.ParticipantPermissions_NoPermissions
}
func convertStatus(status list.AclStatus) model.ParticipantStatus {
switch status {
case list.StatusJoining:
return model.ParticipantStatus_Joining
case list.StatusActive:
return model.ParticipantStatus_Active
case list.StatusRemoved:
return model.ParticipantStatus_Removed
case list.StatusDeclined:
return model.ParticipantStatus_Declined
case list.StatusRemoving:
return model.ParticipantStatus_Removing
case list.StatusCanceled:
return model.ParticipantStatus_Canceled
}
return model.ParticipantStatus_Active
return nil
}
func decryptAll(states []list.AccountState, decrypt func(key crypto.PubKey) ([]byte, error)) (decrypted []list.AccountState, err error) {
@ -369,35 +225,3 @@ func decryptAll(states []list.AccountState, decrypt func(key crypto.PubKey) ([]b
}
return
}
func getSymKey(metadata []byte) (crypto.SymKey, error) {
md := &model.Metadata{}
err := md.Unmarshal(metadata)
if err != nil {
return nil, err
}
keyProto := &cryptoproto.Key{}
err = keyProto.Unmarshal(md.GetIdentity().GetProfileSymKey())
if err != nil {
return nil, err
}
return crypto.UnmarshallAESKey(keyProto.Data)
}
func buildParticipantDetails(
id string,
spaceId string,
identity string,
permissions model.ParticipantPermissions,
status model.ParticipantStatus,
) *types.Struct {
return &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(id),
bundle.RelationKeyIdentity.String(): pbtypes.String(identity),
bundle.RelationKeySpaceId.String(): pbtypes.String(spaceId),
bundle.RelationKeyLastModifiedBy.String(): pbtypes.String(id),
bundle.RelationKeyParticipantPermissions.String(): pbtypes.Int64(int64(permissions)),
bundle.RelationKeyParticipantStatus.String(): pbtypes.Int64(int64(status)),
bundle.RelationKeyIsHiddenDiscovery.String(): pbtypes.Bool(status != model.ParticipantStatus_Active),
}}
}

View file

@ -11,10 +11,10 @@ import (
"github.com/anyproto/anytype-heart/space/clientspace"
dependencies2 "github.com/anyproto/anytype-heart/space/internal/components/dependencies"
"github.com/anyproto/anytype-heart/space/internal/components/spacestatus"
"github.com/anyproto/anytype-heart/space/internal/techspace"
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spacecore/storage"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
const CName = "client.components.builder"

View file

@ -0,0 +1,195 @@
package participantwatcher
import (
"context"
"sync"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anyproto/any-sync/commonspace/object/acl/list"
"github.com/anyproto/any-sync/util/crypto"
"github.com/anyproto/any-sync/util/crypto/cryptoproto"
"github.com/gogo/protobuf/types"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/space/clientspace"
"github.com/anyproto/anytype-heart/space/internal/components/dependencies"
"github.com/anyproto/anytype-heart/space/internal/components/spacestatus"
"github.com/anyproto/anytype-heart/space/spaceinfo"
)
const CName = "common.components.participantwatcher"
var log = logger.NewNamed(CName)
type ParticipantWatcher interface {
app.ComponentRunnable
RegisterIdentity(ctx context.Context, space clientspace.Space, accState list.AccountState) error
RegisterOwnerIdentity(ctx context.Context, space clientspace.Space) error
UpdateParticipantFromAclState(ctx context.Context, space clientspace.Space, accState list.AccountState) error
}
type participant interface {
ModifyIdentityDetails(profile *model.IdentityProfile) (err error)
ModifyOwnerDetails(profileDetails *types.Struct, aclInfo spaceinfo.ParticipantAclInfo) (err error)
ModifyParticipantAclState(accState spaceinfo.ParticipantAclInfo) (err error)
}
var _ ParticipantWatcher = (*participantWatcher)(nil)
type participantWatcher struct {
identityService dependencies.IdentityService
modifier dependencies.DetailsModifier
status spacestatus.SpaceStatus
mx sync.Mutex
addedParticipants map[string]struct{}
}
func New() ParticipantWatcher {
return &participantWatcher{
addedParticipants: map[string]struct{}{},
}
}
func (p *participantWatcher) RegisterIdentity(ctx context.Context, space clientspace.Space, state list.AccountState) (err error) {
p.mx.Lock()
defer p.mx.Unlock()
key, err := getSymKey(state.RequestMetadata)
if err != nil {
return
}
accKey := state.PubKey.Account()
if _, exists := p.addedParticipants[state.PubKey.Account()]; exists {
return
}
err = p.identityService.RegisterIdentity(space.Id(), state.PubKey.Account(), key, func(identity string, profile *model.IdentityProfile) {
err := p.updateParticipantFromIdentity(ctx, space, identity, profile)
if err != nil {
log.Error("error updating participant from identity", zap.Error(err))
}
},
)
if err != nil {
return err
}
p.addedParticipants[accKey] = struct{}{}
return
}
func (p *participantWatcher) Init(a *app.App) (err error) {
p.identityService = app.MustComponent[dependencies.IdentityService](a)
p.modifier = app.MustComponent[dependencies.DetailsModifier](a)
p.status = app.MustComponent[spacestatus.SpaceStatus](a)
return nil
}
func (p *participantWatcher) Name() (name string) {
return CName
}
func (p *participantWatcher) Close(ctx context.Context) (err error) {
p.identityService.UnregisterIdentitiesInSpace(p.status.SpaceId())
return
}
func (p *participantWatcher) RegisterOwnerIdentity(ctx context.Context, space clientspace.Space) error {
p.mx.Lock()
defer p.mx.Unlock()
myIdentity, metadataKey, profileDetails := p.identityService.GetMyProfileDetails()
id := domain.NewParticipantId(space.Id(), myIdentity)
err := space.Do(id, func(sb smartblock.SmartBlock) error {
return sb.(participant).ModifyOwnerDetails(profileDetails, spaceinfo.ParticipantAclInfo{
Id: id,
SpaceId: space.Id(),
Identity: myIdentity,
Permissions: model.ParticipantPermissions_Owner,
Status: model.ParticipantStatus_Active,
})
})
if err != nil {
return err
}
err = p.identityService.RegisterIdentity(space.Id(), myIdentity, metadataKey, func(identity string, profile *model.IdentityProfile) {
err := p.updateParticipantFromIdentity(ctx, space, identity, profile)
if err != nil {
log.Error("error updating participant from identity", zap.Error(err))
}
})
if err != nil {
return err
}
p.addedParticipants[myIdentity] = struct{}{}
return nil
}
func (p *participantWatcher) UpdateParticipantFromAclState(ctx context.Context, space clientspace.Space, accState list.AccountState) error {
id := domain.NewParticipantId(space.Id(), accState.PubKey.Account())
return space.Do(id, func(sb smartblock.SmartBlock) error {
return sb.(participant).ModifyParticipantAclState(spaceinfo.ParticipantAclInfo{
Id: id,
SpaceId: space.Id(),
Identity: accState.PubKey.Account(),
Permissions: convertPermissions(accState.Permissions),
Status: convertStatus(accState.Status),
})
})
}
func (p *participantWatcher) updateParticipantFromIdentity(ctx context.Context, space clientspace.Space, identity string, profile *model.IdentityProfile) (err error) {
id := domain.NewParticipantId(space.Id(), identity)
return space.Do(id, func(sb smartblock.SmartBlock) error {
return sb.(participant).ModifyIdentityDetails(profile)
})
}
func (p *participantWatcher) Run(ctx context.Context) error {
return nil
}
func getSymKey(metadata []byte) (crypto.SymKey, error) {
md := &model.Metadata{}
err := md.Unmarshal(metadata)
if err != nil {
return nil, err
}
keyProto := &cryptoproto.Key{}
err = keyProto.Unmarshal(md.GetIdentity().GetProfileSymKey())
if err != nil {
return nil, err
}
return crypto.UnmarshallAESKey(keyProto.Data)
}
func convertPermissions(permissions list.AclPermissions) model.ParticipantPermissions {
switch aclrecordproto.AclUserPermissions(permissions) {
case aclrecordproto.AclUserPermissions_Writer:
return model.ParticipantPermissions_Writer
case aclrecordproto.AclUserPermissions_Reader:
return model.ParticipantPermissions_Reader
case aclrecordproto.AclUserPermissions_Owner:
return model.ParticipantPermissions_Owner
}
return model.ParticipantPermissions_NoPermissions
}
func convertStatus(status list.AclStatus) model.ParticipantStatus {
switch status {
case list.StatusJoining:
return model.ParticipantStatus_Joining
case list.StatusActive:
return model.ParticipantStatus_Active
case list.StatusRemoved:
return model.ParticipantStatus_Removed
case list.StatusDeclined:
return model.ParticipantStatus_Declined
case list.StatusRemoving:
return model.ParticipantStatus_Removing
case list.StatusCanceled:
return model.ParticipantStatus_Canceled
}
return model.ParticipantStatus_Active
}

View file

@ -11,9 +11,9 @@ import (
"github.com/anyproto/anytype-heart/space/clientspace"
"github.com/anyproto/anytype-heart/space/internal/components/builder"
"github.com/anyproto/anytype-heart/space/internal/components/spacestatus"
"github.com/anyproto/anytype-heart/space/internal/techspace"
spaceservice "github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
const CName = "client.components.spaceloader"

View file

@ -6,8 +6,8 @@ import (
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/debugstat"
"github.com/anyproto/anytype-heart/space/internal/techspace"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
const CName = "client.components.spacestatus"

View file

@ -11,9 +11,9 @@ import (
"github.com/anyproto/anytype-heart/space/internal/spacecontroller"
"github.com/anyproto/anytype-heart/space/internal/spaceprocess/loader"
"github.com/anyproto/anytype-heart/space/internal/spaceprocess/mode"
"github.com/anyproto/anytype-heart/space/internal/techspace"
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
func NewSpaceController(spaceId string, metadata []byte, a *app.App) spacecontroller.SpaceController {

View file

@ -207,12 +207,59 @@ func (_c *MockSpaceController_Mode_Call) RunAndReturn(run func() mode.Mode) *Moc
return _c
}
// SetInfo provides a mock function with given fields: ctx, info
func (_m *MockSpaceController) SetInfo(ctx context.Context, info spaceinfo.SpacePersistentInfo) error {
// SetLocalInfo provides a mock function with given fields: ctx, status
func (_m *MockSpaceController) SetLocalInfo(ctx context.Context, status spaceinfo.SpaceLocalInfo) error {
ret := _m.Called(ctx, status)
if len(ret) == 0 {
panic("no return value specified for SetLocalInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, spaceinfo.SpaceLocalInfo) error); ok {
r0 = rf(ctx, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceController_SetLocalInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetLocalInfo'
type MockSpaceController_SetLocalInfo_Call struct {
*mock.Call
}
// SetLocalInfo is a helper method to define mock.On call
// - ctx context.Context
// - status spaceinfo.SpaceLocalInfo
func (_e *MockSpaceController_Expecter) SetLocalInfo(ctx interface{}, status interface{}) *MockSpaceController_SetLocalInfo_Call {
return &MockSpaceController_SetLocalInfo_Call{Call: _e.mock.On("SetLocalInfo", ctx, status)}
}
func (_c *MockSpaceController_SetLocalInfo_Call) Run(run func(ctx context.Context, status spaceinfo.SpaceLocalInfo)) *MockSpaceController_SetLocalInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(spaceinfo.SpaceLocalInfo))
})
return _c
}
func (_c *MockSpaceController_SetLocalInfo_Call) Return(_a0 error) *MockSpaceController_SetLocalInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceController_SetLocalInfo_Call) RunAndReturn(run func(context.Context, spaceinfo.SpaceLocalInfo) error) *MockSpaceController_SetLocalInfo_Call {
_c.Call.Return(run)
return _c
}
// SetPersistentInfo provides a mock function with given fields: ctx, info
func (_m *MockSpaceController) SetPersistentInfo(ctx context.Context, info spaceinfo.SpacePersistentInfo) error {
ret := _m.Called(ctx, info)
if len(ret) == 0 {
panic("no return value specified for SetInfo")
panic("no return value specified for SetPersistentInfo")
}
var r0 error
@ -225,31 +272,31 @@ func (_m *MockSpaceController) SetInfo(ctx context.Context, info spaceinfo.Space
return r0
}
// MockSpaceController_SetInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetInfo'
type MockSpaceController_SetInfo_Call struct {
// MockSpaceController_SetPersistentInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPersistentInfo'
type MockSpaceController_SetPersistentInfo_Call struct {
*mock.Call
}
// SetInfo is a helper method to define mock.On call
// SetPersistentInfo is a helper method to define mock.On call
// - ctx context.Context
// - info spaceinfo.SpacePersistentInfo
func (_e *MockSpaceController_Expecter) SetInfo(ctx interface{}, info interface{}) *MockSpaceController_SetInfo_Call {
return &MockSpaceController_SetInfo_Call{Call: _e.mock.On("SetInfo", ctx, info)}
func (_e *MockSpaceController_Expecter) SetPersistentInfo(ctx interface{}, info interface{}) *MockSpaceController_SetPersistentInfo_Call {
return &MockSpaceController_SetPersistentInfo_Call{Call: _e.mock.On("SetPersistentInfo", ctx, info)}
}
func (_c *MockSpaceController_SetInfo_Call) Run(run func(ctx context.Context, info spaceinfo.SpacePersistentInfo)) *MockSpaceController_SetInfo_Call {
func (_c *MockSpaceController_SetPersistentInfo_Call) Run(run func(ctx context.Context, info spaceinfo.SpacePersistentInfo)) *MockSpaceController_SetPersistentInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(spaceinfo.SpacePersistentInfo))
})
return _c
}
func (_c *MockSpaceController_SetInfo_Call) Return(_a0 error) *MockSpaceController_SetInfo_Call {
func (_c *MockSpaceController_SetPersistentInfo_Call) Return(_a0 error) *MockSpaceController_SetPersistentInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceController_SetInfo_Call) RunAndReturn(run func(context.Context, spaceinfo.SpacePersistentInfo) error) *MockSpaceController_SetInfo_Call {
func (_c *MockSpaceController_SetPersistentInfo_Call) RunAndReturn(run func(context.Context, spaceinfo.SpacePersistentInfo) error) *MockSpaceController_SetPersistentInfo_Call {
_c.Call.Return(run)
return _c
}
@ -345,17 +392,17 @@ func (_c *MockSpaceController_Start_Call) RunAndReturn(run func(context.Context)
return _c
}
// UpdateInfo provides a mock function with given fields: ctx, info
func (_m *MockSpaceController) UpdateInfo(ctx context.Context, info spaceinfo.SpacePersistentInfo) error {
ret := _m.Called(ctx, info)
// Update provides a mock function with given fields:
func (_m *MockSpaceController) Update() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for UpdateInfo")
panic("no return value specified for Update")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, spaceinfo.SpacePersistentInfo) error); ok {
r0 = rf(ctx, info)
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
@ -363,78 +410,29 @@ func (_m *MockSpaceController) UpdateInfo(ctx context.Context, info spaceinfo.Sp
return r0
}
// MockSpaceController_UpdateInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateInfo'
type MockSpaceController_UpdateInfo_Call struct {
// MockSpaceController_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update'
type MockSpaceController_Update_Call struct {
*mock.Call
}
// UpdateInfo is a helper method to define mock.On call
// - ctx context.Context
// - info spaceinfo.SpacePersistentInfo
func (_e *MockSpaceController_Expecter) UpdateInfo(ctx interface{}, info interface{}) *MockSpaceController_UpdateInfo_Call {
return &MockSpaceController_UpdateInfo_Call{Call: _e.mock.On("UpdateInfo", ctx, info)}
// Update is a helper method to define mock.On call
func (_e *MockSpaceController_Expecter) Update() *MockSpaceController_Update_Call {
return &MockSpaceController_Update_Call{Call: _e.mock.On("Update")}
}
func (_c *MockSpaceController_UpdateInfo_Call) Run(run func(ctx context.Context, info spaceinfo.SpacePersistentInfo)) *MockSpaceController_UpdateInfo_Call {
func (_c *MockSpaceController_Update_Call) Run(run func()) *MockSpaceController_Update_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(spaceinfo.SpacePersistentInfo))
run()
})
return _c
}
func (_c *MockSpaceController_UpdateInfo_Call) Return(_a0 error) *MockSpaceController_UpdateInfo_Call {
func (_c *MockSpaceController_Update_Call) Return(_a0 error) *MockSpaceController_Update_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceController_UpdateInfo_Call) RunAndReturn(run func(context.Context, spaceinfo.SpacePersistentInfo) error) *MockSpaceController_UpdateInfo_Call {
_c.Call.Return(run)
return _c
}
// UpdateRemoteStatus provides a mock function with given fields: ctx, status
func (_m *MockSpaceController) SetRemoteStatus(ctx context.Context, status spaceinfo.SpaceRemoteStatusInfo) error {
ret := _m.Called(ctx, status)
if len(ret) == 0 {
panic("no return value specified for UpdateRemoteStatus")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, spaceinfo.SpaceRemoteStatusInfo) error); ok {
r0 = rf(ctx, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceController_UpdateRemoteStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateRemoteStatus'
type MockSpaceController_UpdateRemoteStatus_Call struct {
*mock.Call
}
// UpdateRemoteStatus is a helper method to define mock.On call
// - ctx context.Context
// - status spaceinfo.SpaceRemoteStatusInfo
func (_e *MockSpaceController_Expecter) UpdateRemoteStatus(ctx interface{}, status interface{}) *MockSpaceController_UpdateRemoteStatus_Call {
return &MockSpaceController_UpdateRemoteStatus_Call{Call: _e.mock.On("UpdateRemoteStatus", ctx, status)}
}
func (_c *MockSpaceController_UpdateRemoteStatus_Call) Run(run func(ctx context.Context, status spaceinfo.SpaceRemoteStatusInfo)) *MockSpaceController_UpdateRemoteStatus_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(spaceinfo.SpaceRemoteStatusInfo))
})
return _c
}
func (_c *MockSpaceController_UpdateRemoteStatus_Call) Return(_a0 error) *MockSpaceController_UpdateRemoteStatus_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceController_UpdateRemoteStatus_Call) RunAndReturn(run func(context.Context, spaceinfo.SpaceRemoteStatusInfo) error) *MockSpaceController_UpdateRemoteStatus_Call {
func (_c *MockSpaceController_Update_Call) RunAndReturn(run func() error) *MockSpaceController_Update_Call {
_c.Call.Return(run)
return _c
}

View file

@ -9,6 +9,7 @@ import (
"github.com/anyproto/anytype-heart/space/internal/components/aclnotifications"
"github.com/anyproto/anytype-heart/space/internal/components/aclobjectmanager"
"github.com/anyproto/anytype-heart/space/internal/components/builder"
"github.com/anyproto/anytype-heart/space/internal/components/participantwatcher"
"github.com/anyproto/anytype-heart/space/internal/components/spaceloader"
"github.com/anyproto/anytype-heart/space/internal/components/spacestatus"
"github.com/anyproto/anytype-heart/space/internal/spaceprocess/mode"
@ -40,7 +41,8 @@ func New(app *app.App, params Params) Loader {
Register(builder.New()).
Register(spaceloader.New(params.IsPersonal, false)).
Register(aclnotifications.NewAclNotificationSender()).
Register(aclobjectmanager.New(params.OwnerMetadata))
Register(aclobjectmanager.New(params.OwnerMetadata)).
Register(participantwatcher.New())
return &loader{
app: child,
}

View file

@ -1,239 +0,0 @@
// Code generated by mockery. DO NOT EDIT.
package mock_techspace
import (
spaceinfo "github.com/anyproto/anytype-heart/space/spaceinfo"
mock "github.com/stretchr/testify/mock"
types "github.com/gogo/protobuf/types"
)
// MockSpaceView is an autogenerated mock type for the SpaceView type
type MockSpaceView struct {
mock.Mock
}
type MockSpaceView_Expecter struct {
mock *mock.Mock
}
func (_m *MockSpaceView) EXPECT() *MockSpaceView_Expecter {
return &MockSpaceView_Expecter{mock: &_m.Mock}
}
// Lock provides a mock function with given fields:
func (_m *MockSpaceView) Lock() {
_m.Called()
}
// MockSpaceView_Lock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Lock'
type MockSpaceView_Lock_Call struct {
*mock.Call
}
// Lock is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) Lock() *MockSpaceView_Lock_Call {
return &MockSpaceView_Lock_Call{Call: _e.mock.On("Lock")}
}
func (_c *MockSpaceView_Lock_Call) Run(run func()) *MockSpaceView_Lock_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_Lock_Call) Return() *MockSpaceView_Lock_Call {
_c.Call.Return()
return _c
}
func (_c *MockSpaceView_Lock_Call) RunAndReturn(run func()) *MockSpaceView_Lock_Call {
_c.Call.Return(run)
return _c
}
// SetSpaceData provides a mock function with given fields: details
func (_m *MockSpaceView) SetSpaceData(details *types.Struct) error {
ret := _m.Called(details)
if len(ret) == 0 {
panic("no return value specified for SetSpaceData")
}
var r0 error
if rf, ok := ret.Get(0).(func(*types.Struct) error); ok {
r0 = rf(details)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpaceData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpaceData'
type MockSpaceView_SetSpaceData_Call struct {
*mock.Call
}
// SetSpaceData is a helper method to define mock.On call
// - details *types.Struct
func (_e *MockSpaceView_Expecter) SetSpaceData(details interface{}) *MockSpaceView_SetSpaceData_Call {
return &MockSpaceView_SetSpaceData_Call{Call: _e.mock.On("SetSpaceData", details)}
}
func (_c *MockSpaceView_SetSpaceData_Call) Run(run func(details *types.Struct)) *MockSpaceView_SetSpaceData_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*types.Struct))
})
return _c
}
func (_c *MockSpaceView_SetSpaceData_Call) Return(_a0 error) *MockSpaceView_SetSpaceData_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpaceData_Call) RunAndReturn(run func(*types.Struct) error) *MockSpaceView_SetSpaceData_Call {
_c.Call.Return(run)
return _c
}
// SetSpaceLocalInfo provides a mock function with given fields: info
func (_m *MockSpaceView) SetSpaceLocalInfo(info spaceinfo.SpaceLocalInfo) error {
ret := _m.Called(info)
if len(ret) == 0 {
panic("no return value specified for SetSpaceLocalInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(spaceinfo.SpaceLocalInfo) error); ok {
r0 = rf(info)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpaceLocalInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpaceLocalInfo'
type MockSpaceView_SetSpaceLocalInfo_Call struct {
*mock.Call
}
// SetSpaceLocalInfo is a helper method to define mock.On call
// - info spaceinfo.SpaceLocalInfo
func (_e *MockSpaceView_Expecter) SetSpaceLocalInfo(info interface{}) *MockSpaceView_SetSpaceLocalInfo_Call {
return &MockSpaceView_SetSpaceLocalInfo_Call{Call: _e.mock.On("SetSpaceLocalInfo", info)}
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) Run(run func(info spaceinfo.SpaceLocalInfo)) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(spaceinfo.SpaceLocalInfo))
})
return _c
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) Return(_a0 error) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) RunAndReturn(run func(spaceinfo.SpaceLocalInfo) error) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Return(run)
return _c
}
// SetSpacePersistentInfo provides a mock function with given fields: info
func (_m *MockSpaceView) SetSpacePersistentInfo(info spaceinfo.SpacePersistentInfo) error {
ret := _m.Called(info)
if len(ret) == 0 {
panic("no return value specified for SetSpacePersistentInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(spaceinfo.SpacePersistentInfo) error); ok {
r0 = rf(info)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpacePersistentInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpacePersistentInfo'
type MockSpaceView_SetSpacePersistentInfo_Call struct {
*mock.Call
}
// SetSpacePersistentInfo is a helper method to define mock.On call
// - info spaceinfo.SpacePersistentInfo
func (_e *MockSpaceView_Expecter) SetSpacePersistentInfo(info interface{}) *MockSpaceView_SetSpacePersistentInfo_Call {
return &MockSpaceView_SetSpacePersistentInfo_Call{Call: _e.mock.On("SetSpacePersistentInfo", info)}
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) Run(run func(info spaceinfo.SpacePersistentInfo)) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(spaceinfo.SpacePersistentInfo))
})
return _c
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) Return(_a0 error) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) RunAndReturn(run func(spaceinfo.SpacePersistentInfo) error) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Return(run)
return _c
}
// Unlock provides a mock function with given fields:
func (_m *MockSpaceView) Unlock() {
_m.Called()
}
// MockSpaceView_Unlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unlock'
type MockSpaceView_Unlock_Call struct {
*mock.Call
}
// Unlock is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) Unlock() *MockSpaceView_Unlock_Call {
return &MockSpaceView_Unlock_Call{Call: _e.mock.On("Unlock")}
}
func (_c *MockSpaceView_Unlock_Call) Run(run func()) *MockSpaceView_Unlock_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_Unlock_Call) Return() *MockSpaceView_Unlock_Call {
_c.Call.Return()
return _c
}
func (_c *MockSpaceView_Unlock_Call) RunAndReturn(run func()) *MockSpaceView_Unlock_Call {
_c.Call.Return(run)
return _c
}
// NewMockSpaceView creates a new instance of MockSpaceView. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockSpaceView(t interface {
mock.TestingT
Cleanup(func())
}) *MockSpaceView {
mock := &MockSpaceView{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View file

@ -20,11 +20,9 @@ func (s *service) Join(ctx context.Context, id, aclHeadId string) error {
ctrl := s.spaceControllers[id]
s.mu.Unlock()
if ctrl.Mode() != mode.ModeJoining {
return ctrl.SetPersistentInfo(ctx, spaceinfo.SpacePersistentInfo{
SpaceID: id,
AccountStatus: spaceinfo.AccountStatusJoining,
AclHeadId: aclHeadId,
})
info := spaceinfo.NewSpacePersistentInfo(id)
info.SetAclHeadId(aclHeadId).SetAccountStatus(spaceinfo.AccountStatusJoining)
return ctrl.SetPersistentInfo(ctx, info)
}
return nil
}
@ -52,8 +50,7 @@ func (s *service) Join(ctx context.Context, id, aclHeadId string) error {
}
func (s *service) CancelLeave(ctx context.Context, id string) error {
return s.techSpace.SetPersistentInfo(ctx, spaceinfo.SpacePersistentInfo{
SpaceID: id,
AccountStatus: spaceinfo.AccountStatusActive,
})
info := spaceinfo.NewSpacePersistentInfo(id)
info.SetAccountStatus(spaceinfo.AccountStatusActive)
return s.techSpace.SetPersistentInfo(ctx, info)
}

View file

@ -29,10 +29,10 @@ import (
"github.com/anyproto/anytype-heart/space/internal/spacecontroller"
"github.com/anyproto/anytype-heart/space/internal/spacecontroller/mock_spacecontroller"
"github.com/anyproto/anytype-heart/space/internal/spaceprocess/mode"
"github.com/anyproto/anytype-heart/space/internal/techspace/mock_techspace"
"github.com/anyproto/anytype-heart/space/spacecore/mock_spacecore"
"github.com/anyproto/anytype-heart/space/spacefactory/mock_spacefactory"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace/mock_techspace"
"github.com/anyproto/anytype-heart/tests/testutil"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

View file

@ -15,10 +15,10 @@ import (
"github.com/anyproto/anytype-heart/space/internal/personalspace"
"github.com/anyproto/anytype-heart/space/internal/shareablespace"
"github.com/anyproto/anytype-heart/space/internal/spacecontroller"
"github.com/anyproto/anytype-heart/space/internal/techspace"
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spacecore/storage"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
type SpaceFactory interface {

View file

@ -0,0 +1,11 @@
package spaceinfo
import "github.com/anyproto/anytype-heart/pkg/lib/pb/model"
type ParticipantAclInfo struct {
Id string
SpaceId string
Identity string
Permissions model.ParticipantPermissions
Status model.ParticipantStatus
}

View file

@ -115,3 +115,8 @@ const (
AccessTypePersonal = AccessType(model.SpaceAccessType_Personal)
AccessTypeShared = AccessType(model.SpaceAccessType_Shared)
)
type SpaceDescription struct {
Name string
IconImage string
}

View file

@ -0,0 +1,623 @@
// Code generated by mockery. DO NOT EDIT.
package mock_techspace
import (
spaceinfo "github.com/anyproto/anytype-heart/space/spaceinfo"
mock "github.com/stretchr/testify/mock"
types "github.com/gogo/protobuf/types"
)
// MockSpaceView is an autogenerated mock type for the SpaceView type
type MockSpaceView struct {
mock.Mock
}
type MockSpaceView_Expecter struct {
mock *mock.Mock
}
func (_m *MockSpaceView) EXPECT() *MockSpaceView_Expecter {
return &MockSpaceView_Expecter{mock: &_m.Mock}
}
// GetExistingInviteInfo provides a mock function with given fields:
func (_m *MockSpaceView) GetExistingInviteInfo() (string, string) {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for GetExistingInviteInfo")
}
var r0 string
var r1 string
if rf, ok := ret.Get(0).(func() (string, string)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func() string); ok {
r1 = rf()
} else {
r1 = ret.Get(1).(string)
}
return r0, r1
}
// MockSpaceView_GetExistingInviteInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetExistingInviteInfo'
type MockSpaceView_GetExistingInviteInfo_Call struct {
*mock.Call
}
// GetExistingInviteInfo is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) GetExistingInviteInfo() *MockSpaceView_GetExistingInviteInfo_Call {
return &MockSpaceView_GetExistingInviteInfo_Call{Call: _e.mock.On("GetExistingInviteInfo")}
}
func (_c *MockSpaceView_GetExistingInviteInfo_Call) Run(run func()) *MockSpaceView_GetExistingInviteInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_GetExistingInviteInfo_Call) Return(fileCid string, fileKey string) *MockSpaceView_GetExistingInviteInfo_Call {
_c.Call.Return(fileCid, fileKey)
return _c
}
func (_c *MockSpaceView_GetExistingInviteInfo_Call) RunAndReturn(run func() (string, string)) *MockSpaceView_GetExistingInviteInfo_Call {
_c.Call.Return(run)
return _c
}
// GetLocalInfo provides a mock function with given fields:
func (_m *MockSpaceView) GetLocalInfo() spaceinfo.SpaceLocalInfo {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for GetLocalInfo")
}
var r0 spaceinfo.SpaceLocalInfo
if rf, ok := ret.Get(0).(func() spaceinfo.SpaceLocalInfo); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(spaceinfo.SpaceLocalInfo)
}
return r0
}
// MockSpaceView_GetLocalInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLocalInfo'
type MockSpaceView_GetLocalInfo_Call struct {
*mock.Call
}
// GetLocalInfo is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) GetLocalInfo() *MockSpaceView_GetLocalInfo_Call {
return &MockSpaceView_GetLocalInfo_Call{Call: _e.mock.On("GetLocalInfo")}
}
func (_c *MockSpaceView_GetLocalInfo_Call) Run(run func()) *MockSpaceView_GetLocalInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_GetLocalInfo_Call) Return(_a0 spaceinfo.SpaceLocalInfo) *MockSpaceView_GetLocalInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_GetLocalInfo_Call) RunAndReturn(run func() spaceinfo.SpaceLocalInfo) *MockSpaceView_GetLocalInfo_Call {
_c.Call.Return(run)
return _c
}
// GetPersistentInfo provides a mock function with given fields:
func (_m *MockSpaceView) GetPersistentInfo() spaceinfo.SpacePersistentInfo {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for GetPersistentInfo")
}
var r0 spaceinfo.SpacePersistentInfo
if rf, ok := ret.Get(0).(func() spaceinfo.SpacePersistentInfo); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(spaceinfo.SpacePersistentInfo)
}
return r0
}
// MockSpaceView_GetPersistentInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPersistentInfo'
type MockSpaceView_GetPersistentInfo_Call struct {
*mock.Call
}
// GetPersistentInfo is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) GetPersistentInfo() *MockSpaceView_GetPersistentInfo_Call {
return &MockSpaceView_GetPersistentInfo_Call{Call: _e.mock.On("GetPersistentInfo")}
}
func (_c *MockSpaceView_GetPersistentInfo_Call) Run(run func()) *MockSpaceView_GetPersistentInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_GetPersistentInfo_Call) Return(_a0 spaceinfo.SpacePersistentInfo) *MockSpaceView_GetPersistentInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_GetPersistentInfo_Call) RunAndReturn(run func() spaceinfo.SpacePersistentInfo) *MockSpaceView_GetPersistentInfo_Call {
_c.Call.Return(run)
return _c
}
// GetSpaceDescription provides a mock function with given fields:
func (_m *MockSpaceView) GetSpaceDescription() spaceinfo.SpaceDescription {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for GetSpaceDescription")
}
var r0 spaceinfo.SpaceDescription
if rf, ok := ret.Get(0).(func() spaceinfo.SpaceDescription); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(spaceinfo.SpaceDescription)
}
return r0
}
// MockSpaceView_GetSpaceDescription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSpaceDescription'
type MockSpaceView_GetSpaceDescription_Call struct {
*mock.Call
}
// GetSpaceDescription is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) GetSpaceDescription() *MockSpaceView_GetSpaceDescription_Call {
return &MockSpaceView_GetSpaceDescription_Call{Call: _e.mock.On("GetSpaceDescription")}
}
func (_c *MockSpaceView_GetSpaceDescription_Call) Run(run func()) *MockSpaceView_GetSpaceDescription_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_GetSpaceDescription_Call) Return(data spaceinfo.SpaceDescription) *MockSpaceView_GetSpaceDescription_Call {
_c.Call.Return(data)
return _c
}
func (_c *MockSpaceView_GetSpaceDescription_Call) RunAndReturn(run func() spaceinfo.SpaceDescription) *MockSpaceView_GetSpaceDescription_Call {
_c.Call.Return(run)
return _c
}
// Lock provides a mock function with given fields:
func (_m *MockSpaceView) Lock() {
_m.Called()
}
// MockSpaceView_Lock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Lock'
type MockSpaceView_Lock_Call struct {
*mock.Call
}
// Lock is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) Lock() *MockSpaceView_Lock_Call {
return &MockSpaceView_Lock_Call{Call: _e.mock.On("Lock")}
}
func (_c *MockSpaceView_Lock_Call) Run(run func()) *MockSpaceView_Lock_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_Lock_Call) Return() *MockSpaceView_Lock_Call {
_c.Call.Return()
return _c
}
func (_c *MockSpaceView_Lock_Call) RunAndReturn(run func()) *MockSpaceView_Lock_Call {
_c.Call.Return(run)
return _c
}
// RemoveExistingInviteInfo provides a mock function with given fields:
func (_m *MockSpaceView) RemoveExistingInviteInfo() (string, error) {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for RemoveExistingInviteInfo")
}
var r0 string
var r1 error
if rf, ok := ret.Get(0).(func() (string, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockSpaceView_RemoveExistingInviteInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveExistingInviteInfo'
type MockSpaceView_RemoveExistingInviteInfo_Call struct {
*mock.Call
}
// RemoveExistingInviteInfo is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) RemoveExistingInviteInfo() *MockSpaceView_RemoveExistingInviteInfo_Call {
return &MockSpaceView_RemoveExistingInviteInfo_Call{Call: _e.mock.On("RemoveExistingInviteInfo")}
}
func (_c *MockSpaceView_RemoveExistingInviteInfo_Call) Run(run func()) *MockSpaceView_RemoveExistingInviteInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_RemoveExistingInviteInfo_Call) Return(fileCid string, err error) *MockSpaceView_RemoveExistingInviteInfo_Call {
_c.Call.Return(fileCid, err)
return _c
}
func (_c *MockSpaceView_RemoveExistingInviteInfo_Call) RunAndReturn(run func() (string, error)) *MockSpaceView_RemoveExistingInviteInfo_Call {
_c.Call.Return(run)
return _c
}
// SetAccessType provides a mock function with given fields: acc
func (_m *MockSpaceView) SetAccessType(acc spaceinfo.AccessType) error {
ret := _m.Called(acc)
if len(ret) == 0 {
panic("no return value specified for SetAccessType")
}
var r0 error
if rf, ok := ret.Get(0).(func(spaceinfo.AccessType) error); ok {
r0 = rf(acc)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetAccessType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAccessType'
type MockSpaceView_SetAccessType_Call struct {
*mock.Call
}
// SetAccessType is a helper method to define mock.On call
// - acc spaceinfo.AccessType
func (_e *MockSpaceView_Expecter) SetAccessType(acc interface{}) *MockSpaceView_SetAccessType_Call {
return &MockSpaceView_SetAccessType_Call{Call: _e.mock.On("SetAccessType", acc)}
}
func (_c *MockSpaceView_SetAccessType_Call) Run(run func(acc spaceinfo.AccessType)) *MockSpaceView_SetAccessType_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(spaceinfo.AccessType))
})
return _c
}
func (_c *MockSpaceView_SetAccessType_Call) Return(_a0 error) *MockSpaceView_SetAccessType_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetAccessType_Call) RunAndReturn(run func(spaceinfo.AccessType) error) *MockSpaceView_SetAccessType_Call {
_c.Call.Return(run)
return _c
}
// SetAclIsEmpty provides a mock function with given fields: isEmpty
func (_m *MockSpaceView) SetAclIsEmpty(isEmpty bool) error {
ret := _m.Called(isEmpty)
if len(ret) == 0 {
panic("no return value specified for SetAclIsEmpty")
}
var r0 error
if rf, ok := ret.Get(0).(func(bool) error); ok {
r0 = rf(isEmpty)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetAclIsEmpty_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAclIsEmpty'
type MockSpaceView_SetAclIsEmpty_Call struct {
*mock.Call
}
// SetAclIsEmpty is a helper method to define mock.On call
// - isEmpty bool
func (_e *MockSpaceView_Expecter) SetAclIsEmpty(isEmpty interface{}) *MockSpaceView_SetAclIsEmpty_Call {
return &MockSpaceView_SetAclIsEmpty_Call{Call: _e.mock.On("SetAclIsEmpty", isEmpty)}
}
func (_c *MockSpaceView_SetAclIsEmpty_Call) Run(run func(isEmpty bool)) *MockSpaceView_SetAclIsEmpty_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(bool))
})
return _c
}
func (_c *MockSpaceView_SetAclIsEmpty_Call) Return(err error) *MockSpaceView_SetAclIsEmpty_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockSpaceView_SetAclIsEmpty_Call) RunAndReturn(run func(bool) error) *MockSpaceView_SetAclIsEmpty_Call {
_c.Call.Return(run)
return _c
}
// SetInviteFileInfo provides a mock function with given fields: fileCid, fileKey
func (_m *MockSpaceView) SetInviteFileInfo(fileCid string, fileKey string) error {
ret := _m.Called(fileCid, fileKey)
if len(ret) == 0 {
panic("no return value specified for SetInviteFileInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(fileCid, fileKey)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetInviteFileInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetInviteFileInfo'
type MockSpaceView_SetInviteFileInfo_Call struct {
*mock.Call
}
// SetInviteFileInfo is a helper method to define mock.On call
// - fileCid string
// - fileKey string
func (_e *MockSpaceView_Expecter) SetInviteFileInfo(fileCid interface{}, fileKey interface{}) *MockSpaceView_SetInviteFileInfo_Call {
return &MockSpaceView_SetInviteFileInfo_Call{Call: _e.mock.On("SetInviteFileInfo", fileCid, fileKey)}
}
func (_c *MockSpaceView_SetInviteFileInfo_Call) Run(run func(fileCid string, fileKey string)) *MockSpaceView_SetInviteFileInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(string))
})
return _c
}
func (_c *MockSpaceView_SetInviteFileInfo_Call) Return(err error) *MockSpaceView_SetInviteFileInfo_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockSpaceView_SetInviteFileInfo_Call) RunAndReturn(run func(string, string) error) *MockSpaceView_SetInviteFileInfo_Call {
_c.Call.Return(run)
return _c
}
// SetSpaceData provides a mock function with given fields: details
func (_m *MockSpaceView) SetSpaceData(details *types.Struct) error {
ret := _m.Called(details)
if len(ret) == 0 {
panic("no return value specified for SetSpaceData")
}
var r0 error
if rf, ok := ret.Get(0).(func(*types.Struct) error); ok {
r0 = rf(details)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpaceData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpaceData'
type MockSpaceView_SetSpaceData_Call struct {
*mock.Call
}
// SetSpaceData is a helper method to define mock.On call
// - details *types.Struct
func (_e *MockSpaceView_Expecter) SetSpaceData(details interface{}) *MockSpaceView_SetSpaceData_Call {
return &MockSpaceView_SetSpaceData_Call{Call: _e.mock.On("SetSpaceData", details)}
}
func (_c *MockSpaceView_SetSpaceData_Call) Run(run func(details *types.Struct)) *MockSpaceView_SetSpaceData_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*types.Struct))
})
return _c
}
func (_c *MockSpaceView_SetSpaceData_Call) Return(_a0 error) *MockSpaceView_SetSpaceData_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpaceData_Call) RunAndReturn(run func(*types.Struct) error) *MockSpaceView_SetSpaceData_Call {
_c.Call.Return(run)
return _c
}
// SetSpaceLocalInfo provides a mock function with given fields: info
func (_m *MockSpaceView) SetSpaceLocalInfo(info spaceinfo.SpaceLocalInfo) error {
ret := _m.Called(info)
if len(ret) == 0 {
panic("no return value specified for SetSpaceLocalInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(spaceinfo.SpaceLocalInfo) error); ok {
r0 = rf(info)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpaceLocalInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpaceLocalInfo'
type MockSpaceView_SetSpaceLocalInfo_Call struct {
*mock.Call
}
// SetSpaceLocalInfo is a helper method to define mock.On call
// - info spaceinfo.SpaceLocalInfo
func (_e *MockSpaceView_Expecter) SetSpaceLocalInfo(info interface{}) *MockSpaceView_SetSpaceLocalInfo_Call {
return &MockSpaceView_SetSpaceLocalInfo_Call{Call: _e.mock.On("SetSpaceLocalInfo", info)}
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) Run(run func(info spaceinfo.SpaceLocalInfo)) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(spaceinfo.SpaceLocalInfo))
})
return _c
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) Return(_a0 error) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpaceLocalInfo_Call) RunAndReturn(run func(spaceinfo.SpaceLocalInfo) error) *MockSpaceView_SetSpaceLocalInfo_Call {
_c.Call.Return(run)
return _c
}
// SetSpacePersistentInfo provides a mock function with given fields: info
func (_m *MockSpaceView) SetSpacePersistentInfo(info spaceinfo.SpacePersistentInfo) error {
ret := _m.Called(info)
if len(ret) == 0 {
panic("no return value specified for SetSpacePersistentInfo")
}
var r0 error
if rf, ok := ret.Get(0).(func(spaceinfo.SpacePersistentInfo) error); ok {
r0 = rf(info)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockSpaceView_SetSpacePersistentInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSpacePersistentInfo'
type MockSpaceView_SetSpacePersistentInfo_Call struct {
*mock.Call
}
// SetSpacePersistentInfo is a helper method to define mock.On call
// - info spaceinfo.SpacePersistentInfo
func (_e *MockSpaceView_Expecter) SetSpacePersistentInfo(info interface{}) *MockSpaceView_SetSpacePersistentInfo_Call {
return &MockSpaceView_SetSpacePersistentInfo_Call{Call: _e.mock.On("SetSpacePersistentInfo", info)}
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) Run(run func(info spaceinfo.SpacePersistentInfo)) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(spaceinfo.SpacePersistentInfo))
})
return _c
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) Return(_a0 error) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockSpaceView_SetSpacePersistentInfo_Call) RunAndReturn(run func(spaceinfo.SpacePersistentInfo) error) *MockSpaceView_SetSpacePersistentInfo_Call {
_c.Call.Return(run)
return _c
}
// Unlock provides a mock function with given fields:
func (_m *MockSpaceView) Unlock() {
_m.Called()
}
// MockSpaceView_Unlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unlock'
type MockSpaceView_Unlock_Call struct {
*mock.Call
}
// Unlock is a helper method to define mock.On call
func (_e *MockSpaceView_Expecter) Unlock() *MockSpaceView_Unlock_Call {
return &MockSpaceView_Unlock_Call{Call: _e.mock.On("Unlock")}
}
func (_c *MockSpaceView_Unlock_Call) Run(run func()) *MockSpaceView_Unlock_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockSpaceView_Unlock_Call) Return() *MockSpaceView_Unlock_Call {
_c.Call.Return()
return _c
}
func (_c *MockSpaceView_Unlock_Call) RunAndReturn(run func()) *MockSpaceView_Unlock_Call {
_c.Call.Return(run)
return _c
}
// NewMockSpaceView creates a new instance of MockSpaceView. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockSpaceView(t interface {
mock.TestingT
Cleanup(func())
}) *MockSpaceView {
mock := &MockSpaceView{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View file

@ -14,6 +14,8 @@ import (
spaceinfo "github.com/anyproto/anytype-heart/space/spaceinfo"
techspace "github.com/anyproto/anytype-heart/space/techspace"
types "github.com/gogo/protobuf/types"
)
@ -76,6 +78,113 @@ func (_c *MockTechSpace_Close_Call) RunAndReturn(run func(context.Context) error
return _c
}
// DoSpaceView provides a mock function with given fields: ctx, spaceID, apply
func (_m *MockTechSpace) DoSpaceView(ctx context.Context, spaceID string, apply func(techspace.SpaceView) error) error {
ret := _m.Called(ctx, spaceID, apply)
if len(ret) == 0 {
panic("no return value specified for DoSpaceView")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, string, func(techspace.SpaceView) error) error); ok {
r0 = rf(ctx, spaceID, apply)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockTechSpace_DoSpaceView_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DoSpaceView'
type MockTechSpace_DoSpaceView_Call struct {
*mock.Call
}
// DoSpaceView is a helper method to define mock.On call
// - ctx context.Context
// - spaceID string
// - apply func(techspace.SpaceView) error
func (_e *MockTechSpace_Expecter) DoSpaceView(ctx interface{}, spaceID interface{}, apply interface{}) *MockTechSpace_DoSpaceView_Call {
return &MockTechSpace_DoSpaceView_Call{Call: _e.mock.On("DoSpaceView", ctx, spaceID, apply)}
}
func (_c *MockTechSpace_DoSpaceView_Call) Run(run func(ctx context.Context, spaceID string, apply func(techspace.SpaceView) error)) *MockTechSpace_DoSpaceView_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string), args[2].(func(techspace.SpaceView) error))
})
return _c
}
func (_c *MockTechSpace_DoSpaceView_Call) Return(err error) *MockTechSpace_DoSpaceView_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockTechSpace_DoSpaceView_Call) RunAndReturn(run func(context.Context, string, func(techspace.SpaceView) error) error) *MockTechSpace_DoSpaceView_Call {
_c.Call.Return(run)
return _c
}
// GetSpaceView provides a mock function with given fields: ctx, spaceId
func (_m *MockTechSpace) GetSpaceView(ctx context.Context, spaceId string) (techspace.SpaceView, error) {
ret := _m.Called(ctx, spaceId)
if len(ret) == 0 {
panic("no return value specified for GetSpaceView")
}
var r0 techspace.SpaceView
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string) (techspace.SpaceView, error)); ok {
return rf(ctx, spaceId)
}
if rf, ok := ret.Get(0).(func(context.Context, string) techspace.SpaceView); ok {
r0 = rf(ctx, spaceId)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(techspace.SpaceView)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
r1 = rf(ctx, spaceId)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockTechSpace_GetSpaceView_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSpaceView'
type MockTechSpace_GetSpaceView_Call struct {
*mock.Call
}
// GetSpaceView is a helper method to define mock.On call
// - ctx context.Context
// - spaceId string
func (_e *MockTechSpace_Expecter) GetSpaceView(ctx interface{}, spaceId interface{}) *MockTechSpace_GetSpaceView_Call {
return &MockTechSpace_GetSpaceView_Call{Call: _e.mock.On("GetSpaceView", ctx, spaceId)}
}
func (_c *MockTechSpace_GetSpaceView_Call) Run(run func(ctx context.Context, spaceId string)) *MockTechSpace_GetSpaceView_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string))
})
return _c
}
func (_c *MockTechSpace_GetSpaceView_Call) Return(_a0 techspace.SpaceView, _a1 error) *MockTechSpace_GetSpaceView_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockTechSpace_GetSpaceView_Call) RunAndReturn(run func(context.Context, string) (techspace.SpaceView, error)) *MockTechSpace_GetSpaceView_Call {
_c.Call.Return(run)
return _c
}
// Init provides a mock function with given fields: a
func (_m *MockTechSpace) Init(a *app.App) error {
ret := _m.Called(a)

View file

@ -40,6 +40,7 @@ type TechSpace interface {
Close(ctx context.Context) (err error)
TechSpaceId() string
DoSpaceView(ctx context.Context, spaceID string, apply func(spaceView SpaceView) error) (err error)
SpaceViewCreate(ctx context.Context, spaceId string, force bool, info spaceinfo.SpacePersistentInfo) (err error)
GetSpaceView(ctx context.Context, spaceId string) (SpaceView, error)
SpaceViewExists(ctx context.Context, spaceId string) (exists bool, err error)
@ -56,11 +57,13 @@ type SpaceView interface {
GetLocalInfo() spaceinfo.SpaceLocalInfo
SetSpaceData(details *types.Struct) error
SetSpaceLocalInfo(info spaceinfo.SpaceLocalInfo) error
SetInviteFileInfo(fileCid string, fileKey string) (err error)
SetAccessType(acc spaceinfo.AccessType) error
SetAclIsEmpty(isEmpty bool) (err error)
SetSpacePersistentInfo(info spaceinfo.SpacePersistentInfo) error
RemoveExistingInvite() (cid string, err error)
ExistingFileInfo() (cid, key string, err error)
RemoveExistingInviteInfo() (fileCid string, err error)
GetSpaceDescription() (data spaceinfo.SpaceDescription)
GetExistingInviteInfo() (fileCid string, fileKey string)
}
func New() TechSpace {
@ -123,19 +126,19 @@ func (s *techSpace) TechSpaceId() string {
}
func (s *techSpace) SetLocalInfo(ctx context.Context, info spaceinfo.SpaceLocalInfo) (err error) {
return s.doSpaceView(ctx, info.SpaceId, func(spaceView SpaceView) error {
return s.DoSpaceView(ctx, info.SpaceId, func(spaceView SpaceView) error {
return spaceView.SetSpaceLocalInfo(info)
})
}
func (s *techSpace) SetAccessType(ctx context.Context, spaceId string, acc spaceinfo.AccessType) (err error) {
return s.doSpaceView(ctx, spaceId, func(spaceView SpaceView) error {
return s.DoSpaceView(ctx, spaceId, func(spaceView SpaceView) error {
return spaceView.SetAccessType(acc)
})
}
func (s *techSpace) SetPersistentInfo(ctx context.Context, info spaceinfo.SpacePersistentInfo) (err error) {
return s.doSpaceView(ctx, info.SpaceID, func(spaceView SpaceView) error {
return s.DoSpaceView(ctx, info.SpaceID, func(spaceView SpaceView) error {
return spaceView.SetSpacePersistentInfo(info)
})
}
@ -184,7 +187,7 @@ func (s *techSpace) GetSpaceView(ctx context.Context, spaceId string) (SpaceView
}
func (s *techSpace) SpaceViewSetData(ctx context.Context, spaceId string, details *types.Struct) (err error) {
return s.doSpaceView(ctx, spaceId, func(spaceView SpaceView) error {
return s.DoSpaceView(ctx, spaceId, func(spaceView SpaceView) error {
return spaceView.SetSpaceData(details)
})
}
@ -227,7 +230,7 @@ func (s *techSpace) deriveSpaceViewID(ctx context.Context, spaceID string) (stri
return payload.RootRawChange.Id, nil
}
func (s *techSpace) doSpaceView(ctx context.Context, spaceID string, apply func(spaceView SpaceView) error) (err error) {
func (s *techSpace) DoSpaceView(ctx context.Context, spaceID string, apply func(spaceView SpaceView) error) (err error) {
viewId, err := s.getViewIdLocked(ctx, spaceID)
if err != nil {
return

22
util/encode/base58.go Normal file
View file

@ -0,0 +1,22 @@
package encode
import (
"github.com/anyproto/any-sync/util/crypto"
"github.com/mr-tron/base58/base58"
)
func EncodeKeyToBase58(key crypto.SymKey) (string, error) {
raw, err := key.Raw()
if err != nil {
return "", err
}
return base58.Encode(raw), nil
}
func DecodeKeyFromBase58(rawString string) (crypto.SymKey, error) {
raw, err := base58.Decode(rawString)
if err != nil {
return nil, err
}
return crypto.UnmarshallAESKey(raw)
}