2020-08-24 14:07:08 +00:00
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2021-05-19 12:04:38 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg"
|
2020-10-07 16:17:50 +00:00
|
|
|
eaclSDK "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
|
|
|
|
containerSDK "github.com/nspcc-dev/neofs-api-go/pkg/container"
|
2021-05-31 11:03:17 +00:00
|
|
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
2020-10-07 16:17:50 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
2021-05-25 15:46:50 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
2020-08-24 14:07:08 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
2021-05-26 10:34:06 +00:00
|
|
|
containercore "github.com/nspcc-dev/neofs-node/pkg/core/container"
|
2020-10-07 16:17:50 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
|
2020-08-24 14:07:08 +00:00
|
|
|
containerSvc "github.com/nspcc-dev/neofs-node/pkg/services/container"
|
2021-08-30 11:16:41 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
|
2020-08-24 14:07:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type morphExecutor struct {
|
2020-10-07 16:17:50 +00:00
|
|
|
wrapper *wrapper.Wrapper
|
2021-08-30 11:16:41 +00:00
|
|
|
|
|
|
|
rdr Reader
|
2021-09-08 13:31:05 +00:00
|
|
|
|
|
|
|
invalidator Invalidator
|
2021-08-30 11:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reader is an interface of read-only container storage.
|
|
|
|
type Reader interface {
|
|
|
|
containercore.Source
|
|
|
|
eacl.Source
|
|
|
|
|
|
|
|
// List returns a list of container identifiers belonging
|
|
|
|
// to the specified owner of NeoFS system. Returns the identifiers
|
|
|
|
// of all NeoFS containers if pointer to owner identifier is nil.
|
|
|
|
List(*owner.ID) ([]*cid.ID, error)
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-09-08 13:31:05 +00:00
|
|
|
// Invalidator is an interface of local cache invalidator. It removes cached
|
|
|
|
// values in order to synchronize updated data in the side chain faster.
|
|
|
|
type Invalidator interface {
|
|
|
|
// InvalidateContainer from the local container cache if it exists.
|
|
|
|
InvalidateContainer(*cid.ID)
|
|
|
|
// InvalidateEACL from the local eACL cache if it exists.
|
|
|
|
InvalidateEACL(*cid.ID)
|
|
|
|
// InvalidateContainerList from the local cache of container list results
|
|
|
|
// if it exists.
|
|
|
|
InvalidateContainerList(*owner.ID)
|
|
|
|
// InvalidateContainerListByCID from the local cache of container list
|
|
|
|
// results if it exists. Container list source uses owner.ID as a key,
|
|
|
|
// so invalidating cache record by the value requires different approach.
|
|
|
|
InvalidateContainerListByCID(*cid.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewExecutor(w *wrapper.Wrapper, rdr Reader, i Invalidator) containerSvc.ServiceExecutor {
|
2020-08-24 14:07:08 +00:00
|
|
|
return &morphExecutor{
|
2021-09-08 13:31:05 +00:00
|
|
|
wrapper: w,
|
|
|
|
rdr: rdr,
|
|
|
|
invalidator: i,
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 16:23:11 +00:00
|
|
|
func (s *morphExecutor) Put(ctx containerSvc.ContextWithToken, body *container.PutRequestBody) (*container.PutResponseBody, error) {
|
2021-07-02 05:59:02 +00:00
|
|
|
cnr := containerSDK.NewContainerFromV2(body.GetContainer())
|
2020-11-03 09:08:24 +00:00
|
|
|
|
2021-05-25 15:25:34 +00:00
|
|
|
cnr.SetSignature(
|
|
|
|
pkg.NewSignatureFromV2(body.GetSignature()),
|
|
|
|
)
|
2020-12-24 10:20:20 +00:00
|
|
|
|
2021-05-25 15:46:50 +00:00
|
|
|
cnr.SetSessionToken(
|
|
|
|
session.NewTokenFromV2(ctx.SessionToken),
|
|
|
|
)
|
|
|
|
|
2021-05-25 15:25:34 +00:00
|
|
|
cid, err := wrapper.Put(s.wrapper, cnr)
|
2020-08-24 14:07:08 +00:00
|
|
|
if err != nil {
|
2020-10-07 16:17:50 +00:00
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-09-08 13:31:05 +00:00
|
|
|
s.invalidator.InvalidateContainerList(cnr.OwnerID())
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
res := new(container.PutResponseBody)
|
2020-10-07 16:17:50 +00:00
|
|
|
res.SetContainerID(cid.ToV2())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2021-05-26 11:08:24 +00:00
|
|
|
func (s *morphExecutor) Delete(ctx containerSvc.ContextWithToken, body *container.DeleteRequestBody) (*container.DeleteResponseBody, error) {
|
2021-05-31 11:03:17 +00:00
|
|
|
id := cid.NewFromV2(body.GetContainerID())
|
2021-05-26 10:34:06 +00:00
|
|
|
sig := body.GetSignature().GetSign()
|
2021-05-26 11:08:24 +00:00
|
|
|
tok := session.NewTokenFromV2(ctx.SessionToken)
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-05-26 10:34:06 +00:00
|
|
|
var rmWitness containercore.RemovalWitness
|
|
|
|
|
2021-05-31 11:03:17 +00:00
|
|
|
rmWitness.SetContainerID(id)
|
2021-05-26 10:34:06 +00:00
|
|
|
rmWitness.SetSignature(sig)
|
2021-05-26 11:08:24 +00:00
|
|
|
rmWitness.SetSessionToken(tok)
|
2021-05-26 10:34:06 +00:00
|
|
|
|
|
|
|
err := wrapper.Delete(s.wrapper, rmWitness)
|
2020-10-07 16:17:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-09-08 13:31:05 +00:00
|
|
|
s.invalidator.InvalidateContainer(id)
|
|
|
|
s.invalidator.InvalidateEACL(id)
|
|
|
|
|
|
|
|
// it is faster to use slower invalidation by CID than making separate
|
|
|
|
// network request to fetch owner ID of the container.
|
|
|
|
s.invalidator.InvalidateContainerListByCID(id)
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
return new(container.DeleteResponseBody), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *morphExecutor) Get(ctx context.Context, body *container.GetRequestBody) (*container.GetResponseBody, error) {
|
2021-05-31 11:03:17 +00:00
|
|
|
id := cid.NewFromV2(body.GetContainerID())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-08-30 11:16:41 +00:00
|
|
|
cnr, err := s.rdr.Get(id)
|
2020-08-24 14:07:08 +00:00
|
|
|
if err != nil {
|
2020-10-07 16:17:50 +00:00
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
res := new(container.GetResponseBody)
|
2020-10-07 16:17:50 +00:00
|
|
|
res.SetContainer(cnr.ToV2())
|
2021-05-25 15:10:34 +00:00
|
|
|
res.SetSignature(cnr.Signature().ToV2())
|
|
|
|
res.SetSessionToken(cnr.SessionToken().ToV2())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *morphExecutor) List(ctx context.Context, body *container.ListRequestBody) (*container.ListResponseBody, error) {
|
2020-10-07 16:17:50 +00:00
|
|
|
oid := owner.NewIDFromV2(body.GetOwnerID())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-08-30 11:16:41 +00:00
|
|
|
cnrs, err := s.rdr.List(oid)
|
2020-08-24 14:07:08 +00:00
|
|
|
if err != nil {
|
2020-10-07 16:17:50 +00:00
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2020-10-07 16:17:50 +00:00
|
|
|
cidList := make([]*refs.ContainerID, 0, len(cnrs))
|
|
|
|
for i := range cnrs {
|
|
|
|
cidList = append(cidList, cnrs[i].ToV2())
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
res := new(container.ListResponseBody)
|
|
|
|
res.SetContainerIDs(cidList)
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2021-05-25 16:25:14 +00:00
|
|
|
func (s *morphExecutor) SetExtendedACL(ctx containerSvc.ContextWithToken, body *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
|
2020-10-07 16:17:50 +00:00
|
|
|
table := eaclSDK.NewTableFromV2(body.GetEACL())
|
2021-05-19 12:04:38 +00:00
|
|
|
sign := pkg.NewSignatureFromV2(body.GetSignature())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-05-25 15:27:12 +00:00
|
|
|
table.SetSignature(sign)
|
|
|
|
|
2021-05-25 16:25:14 +00:00
|
|
|
table.SetSessionToken(
|
|
|
|
session.NewTokenFromV2(ctx.SessionToken),
|
|
|
|
)
|
|
|
|
|
2021-05-25 15:27:12 +00:00
|
|
|
err := wrapper.PutEACL(s.wrapper, table)
|
2021-09-08 13:31:05 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
s.invalidator.InvalidateEACL(table.CID())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-09-08 13:31:05 +00:00
|
|
|
return new(container.SetExtendedACLResponseBody), nil
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2020-10-07 16:17:50 +00:00
|
|
|
func (s *morphExecutor) GetExtendedACL(ctx context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
2021-05-31 11:03:17 +00:00
|
|
|
id := cid.NewFromV2(body.GetContainerID())
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-08-30 11:16:41 +00:00
|
|
|
table, err := s.rdr.GetEACL(id)
|
2020-08-24 14:07:08 +00:00
|
|
|
if err != nil {
|
2020-10-07 16:17:50 +00:00
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
res := new(container.GetExtendedACLResponseBody)
|
2020-10-07 16:17:50 +00:00
|
|
|
res.SetEACL(table.ToV2())
|
2021-05-25 15:18:32 +00:00
|
|
|
res.SetSignature(table.Signature().ToV2())
|
2021-05-25 15:12:23 +00:00
|
|
|
res.SetSessionToken(table.SessionToken().ToV2())
|
2020-09-04 12:18:47 +00:00
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
return res, nil
|
|
|
|
}
|