1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-07 21:47:02 +09:00
any-sync/commonspace/acl/aclclient/acjoiningclient.go
2024-03-26 15:55:12 +01:00

131 lines
3.8 KiB
Go

//go:generate mockgen -destination mock_aclclient/mock_aclclient.go github.com/anyproto/any-sync/commonspace/acl/aclclient AclJoiningClient,AclSpaceClient
package aclclient
import (
"context"
"fmt"
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/commonspace/object/acl/list"
"github.com/anyproto/any-sync/commonspace/object/acl/liststorage"
"github.com/anyproto/any-sync/consensus/consensusproto"
"github.com/anyproto/any-sync/node/nodeclient"
)
const CName = "common.acl.aclclient"
type AclJoiningClient interface {
app.Component
AclGetRecords(ctx context.Context, spaceId, aclHead string) ([]*consensusproto.RawRecordWithId, error)
RequestJoin(ctx context.Context, spaceId string, payload list.RequestJoinPayload) (aclHeadId string, err error)
CancelJoin(ctx context.Context, spaceId string) (err error)
CancelRemoveSelf(ctx context.Context, spaceId string) (err error)
}
type aclJoiningClient struct {
nodeClient nodeclient.NodeClient
keys *accountdata.AccountKeys
}
func NewAclJoiningClient() AclJoiningClient {
return &aclJoiningClient{}
}
func (c *aclJoiningClient) Name() (name string) {
return CName
}
func (c *aclJoiningClient) Init(a *app.App) (err error) {
c.nodeClient = a.MustComponent(nodeclient.CName).(nodeclient.NodeClient)
c.keys = a.MustComponent(accountservice.CName).(accountservice.Service).Account()
return nil
}
func (c *aclJoiningClient) AclGetRecords(ctx context.Context, spaceId, aclHead string) (recs []*consensusproto.RawRecordWithId, err error) {
return c.nodeClient.AclGetRecords(ctx, spaceId, aclHead)
}
func (c *aclJoiningClient) getAcl(ctx context.Context, spaceId string) (l list.AclList, err error) {
res, err := c.AclGetRecords(ctx, spaceId, "")
if err != nil {
return
}
if len(res) == 0 {
err = fmt.Errorf("acl not found")
return
}
storage, err := liststorage.NewInMemoryAclListStorage(res[0].Id, res)
if err != nil {
return
}
return list.BuildAclListWithIdentity(c.keys, storage, list.NoOpAcceptorVerifier{})
}
func (c *aclJoiningClient) CancelJoin(ctx context.Context, spaceId string) (err error) {
acl, err := c.getAcl(ctx, spaceId)
if err != nil {
return
}
pendingReq, err := acl.AclState().JoinRecord(acl.AclState().Identity(), false)
if err != nil {
return
}
res, err := acl.RecordBuilder().BuildRequestCancel(pendingReq.RecordId)
if err != nil {
return
}
_, err = c.nodeClient.AclAddRecord(ctx, spaceId, res)
return
}
func (c *aclJoiningClient) RequestJoin(ctx context.Context, spaceId string, payload list.RequestJoinPayload) (aclHeadId string, err error) {
acl, err := c.getAcl(ctx, spaceId)
if err != nil {
return
}
joinRecs, err := acl.AclState().JoinRecords(false)
if err != nil {
return
}
for _, rec := range joinRecs {
if rec.RequestIdentity.Equals(c.keys.SignKey.GetPublic()) {
// that means that we already requested to join
return
}
}
rec, err := acl.RecordBuilder().BuildRequestJoin(payload)
if err != nil {
return
}
recWithId, err := c.nodeClient.AclAddRecord(ctx, spaceId, rec)
if err != nil {
return
}
aclHeadId = recWithId.Id
return
}
func (c *aclJoiningClient) CancelRemoveSelf(ctx context.Context, spaceId string) (err error) {
acl, err := c.getAcl(ctx, spaceId)
if err != nil {
return
}
pendingReq, err := acl.AclState().Record(acl.AclState().Identity())
if err != nil {
if !acl.AclState().Permissions(acl.AclState().Identity()).NoPermissions() {
return nil
}
return err
}
if pendingReq.Type != list.RequestTypeRemove {
return list.ErrInsufficientPermissions
}
newRec, err := acl.RecordBuilder().BuildRequestCancel(pendingReq.RecordId)
if err != nil {
return
}
_, err = c.nodeClient.AclAddRecord(ctx, spaceId, newRec)
return
}