2020-08-24 14:07:08 +00:00
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-12-16 15:26:13 +00:00
|
|
|
"errors"
|
2022-05-12 16:37:46 +00:00
|
|
|
"fmt"
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2023-03-07 13:38:26 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
|
|
sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
|
|
|
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
|
|
|
containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container"
|
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
|
|
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
2020-08-24 14:07:08 +00:00
|
|
|
)
|
|
|
|
|
2024-03-11 14:55:50 +00:00
|
|
|
var errMissingUserID = errors.New("missing user ID")
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
type morphExecutor struct {
|
2021-08-30 11:16:41 +00:00
|
|
|
rdr Reader
|
2021-09-08 17:24:16 +00:00
|
|
|
wrt Writer
|
2021-08-30 11:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reader is an interface of read-only container storage.
|
|
|
|
type Reader interface {
|
|
|
|
containercore.Source
|
2022-09-08 10:32:25 +00:00
|
|
|
containercore.EACLSource
|
2021-08-30 11:16:41 +00:00
|
|
|
|
2024-02-06 17:29:39 +00:00
|
|
|
// ContainersOf returns a list of container identifiers belonging
|
2023-02-05 15:59:38 +00:00
|
|
|
// to the specified user of FrostFS system. Returns the identifiers
|
|
|
|
// of all FrostFS containers if pointer to owner identifier is nil.
|
2024-02-06 17:29:39 +00:00
|
|
|
ContainersOf(*user.ID) ([]cid.ID, error)
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-09-08 17:24:16 +00:00
|
|
|
// Writer is an interface of container storage updater.
|
|
|
|
type Writer interface {
|
|
|
|
// Put stores specified container in the side chain.
|
2022-06-22 10:55:31 +00:00
|
|
|
Put(containercore.Container) (*cid.ID, error)
|
2021-09-08 17:24:16 +00:00
|
|
|
// Delete removes specified container from the side chain.
|
|
|
|
Delete(containercore.RemovalWitness) error
|
|
|
|
// PutEACL updates extended ACL table of specified container in the side chain.
|
2022-06-22 10:55:31 +00:00
|
|
|
PutEACL(containercore.EACL) error
|
2021-09-08 13:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-09-08 17:24:16 +00:00
|
|
|
func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor {
|
2020-08-24 14:07:08 +00:00
|
|
|
return &morphExecutor{
|
2021-09-08 17:24:16 +00:00
|
|
|
rdr: rdr,
|
|
|
|
wrt: wrt,
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
func (s *morphExecutor) Put(_ context.Context, tokV2 *sessionV2.Token, body *container.PutRequestBody) (*container.PutResponseBody, error) {
|
2022-05-16 13:15:31 +00:00
|
|
|
sigV2 := body.GetSignature()
|
|
|
|
if sigV2 == nil {
|
2023-06-26 13:18:39 +00:00
|
|
|
// TODO(@cthulhu-rider): #468 use "const" error
|
2022-05-16 13:15:31 +00:00
|
|
|
return nil, errors.New("missing signature")
|
|
|
|
}
|
|
|
|
|
2022-06-28 07:01:05 +00:00
|
|
|
cnrV2 := body.GetContainer()
|
|
|
|
if cnrV2 == nil {
|
|
|
|
return nil, errors.New("missing container field")
|
|
|
|
}
|
|
|
|
|
|
|
|
var cnr containercore.Container
|
|
|
|
|
|
|
|
err := cnr.Value.ReadFromV2(*cnrV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid container: %w", err)
|
2022-06-22 10:55:31 +00:00
|
|
|
}
|
2022-05-16 13:15:31 +00:00
|
|
|
|
2022-07-22 14:04:37 +00:00
|
|
|
err = cnr.Signature.ReadFromV2(*sigV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("can't read signature: %w", err)
|
|
|
|
}
|
2020-12-24 10:20:20 +00:00
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
if tokV2 != nil {
|
2022-06-22 10:55:31 +00:00
|
|
|
cnr.Session = new(session.Container)
|
2021-12-16 15:26:13 +00:00
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
err := cnr.Session.ReadFromV2(*tokV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid session token: %w", err)
|
|
|
|
}
|
|
|
|
}
|
2021-05-25 15:46:50 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
idCnr, err := s.wrt.Put(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
|
|
|
}
|
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
var idCnrV2 refs.ContainerID
|
|
|
|
idCnr.WriteToV2(&idCnrV2)
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
res := new(container.PutResponseBody)
|
2022-05-12 16:37:46 +00:00
|
|
|
res.SetContainerID(&idCnrV2)
|
2020-08-24 14:07:08 +00:00
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
func (s *morphExecutor) Delete(_ context.Context, tokV2 *sessionV2.Token, body *container.DeleteRequestBody) (*container.DeleteResponseBody, error) {
|
2022-05-12 16:37:46 +00:00
|
|
|
idV2 := body.GetContainerID()
|
|
|
|
if idV2 == nil {
|
|
|
|
return nil, errors.New("missing container ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
var id cid.ID
|
|
|
|
|
|
|
|
err := id.ReadFromV2(*idV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid container ID: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:20:08 +00:00
|
|
|
var tok *session.Container
|
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
if tokV2 != nil {
|
2022-05-18 15:20:08 +00:00
|
|
|
tok = new(session.Container)
|
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
err := tok.ReadFromV2(*tokV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid session token: %w", err)
|
|
|
|
}
|
2021-12-16 15:26:13 +00:00
|
|
|
}
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2021-05-26 10:34:06 +00:00
|
|
|
var rmWitness containercore.RemovalWitness
|
|
|
|
|
2023-06-01 08:55:06 +00:00
|
|
|
rmWitness.ContainerID = id
|
|
|
|
rmWitness.Signature = body.GetSignature()
|
|
|
|
rmWitness.SessionToken = tok
|
2021-05-26 10:34:06 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
err = s.wrt.Delete(rmWitness)
|
2020-10-07 16:17:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return new(container.DeleteResponseBody), nil
|
|
|
|
}
|
|
|
|
|
2023-04-26 08:24:40 +00:00
|
|
|
func (s *morphExecutor) Get(_ context.Context, body *container.GetRequestBody) (*container.GetResponseBody, error) {
|
2022-05-12 16:37:46 +00:00
|
|
|
idV2 := body.GetContainerID()
|
|
|
|
if idV2 == nil {
|
|
|
|
return nil, errors.New("missing container ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
var id cid.ID
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
err := id.ReadFromV2(*idV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid container ID: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-05-31 17:00: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
|
|
|
}
|
|
|
|
|
2022-07-06 07:54:15 +00:00
|
|
|
sigV2 := new(refs.Signature)
|
2022-06-22 10:55:31 +00:00
|
|
|
cnr.Signature.WriteToV2(sigV2)
|
2022-05-16 13:15:31 +00:00
|
|
|
|
2022-05-18 15:20:08 +00:00
|
|
|
var tokV2 *sessionV2.Token
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
if cnr.Session != nil {
|
2022-05-18 15:20:08 +00:00
|
|
|
tokV2 = new(sessionV2.Token)
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
cnr.Session.WriteToV2(tokV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 07:01:05 +00:00
|
|
|
var cnrV2 container.Container
|
|
|
|
cnr.Value.WriteToV2(&cnrV2)
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
res := new(container.GetResponseBody)
|
2022-06-28 07:01:05 +00:00
|
|
|
res.SetContainer(&cnrV2)
|
2022-05-16 13:15:31 +00:00
|
|
|
res.SetSignature(sigV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
res.SetSessionToken(tokV2)
|
2020-08-24 14:07:08 +00:00
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2023-04-26 08:24:40 +00:00
|
|
|
func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) (*container.ListResponseBody, error) {
|
2022-05-17 13:59:46 +00:00
|
|
|
idV2 := body.GetOwnerID()
|
|
|
|
if idV2 == nil {
|
2024-03-11 14:55:50 +00:00
|
|
|
return nil, errMissingUserID
|
2022-05-17 13:59:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var id user.ID
|
|
|
|
|
|
|
|
err := id.ReadFromV2(*idV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid user ID: %w", err)
|
|
|
|
}
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2024-02-06 17:29:39 +00:00
|
|
|
cnrs, err := s.rdr.ContainersOf(&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
|
|
|
}
|
|
|
|
|
2022-03-15 12:11:35 +00:00
|
|
|
cidList := make([]refs.ContainerID, len(cnrs))
|
2020-10-07 16:17:50 +00:00
|
|
|
for i := range cnrs {
|
2022-05-12 16:37:46 +00:00
|
|
|
cnrs[i].WriteToV2(&cidList[i])
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
res := new(container.ListResponseBody)
|
|
|
|
res.SetContainerIDs(cidList)
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2023-04-26 08:24:40 +00:00
|
|
|
func (s *morphExecutor) SetExtendedACL(_ context.Context, tokV2 *sessionV2.Token, body *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
|
2022-05-16 13:15:31 +00:00
|
|
|
sigV2 := body.GetSignature()
|
|
|
|
if sigV2 == nil {
|
2023-06-26 13:18:39 +00:00
|
|
|
// TODO(@cthulhu-rider): #468 use "const" error
|
2022-05-16 13:15:31 +00:00
|
|
|
return nil, errors.New("missing signature")
|
|
|
|
}
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
eaclInfo := containercore.EACL{
|
|
|
|
Value: eaclSDK.NewTableFromV2(body.GetEACL()),
|
|
|
|
}
|
2022-05-16 13:15:31 +00:00
|
|
|
|
2022-07-22 14:04:37 +00:00
|
|
|
err := eaclInfo.Signature.ReadFromV2(*sigV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("can't read signature: %w", err)
|
|
|
|
}
|
2021-05-25 15:27:12 +00:00
|
|
|
|
2022-03-30 14:19:14 +00:00
|
|
|
if tokV2 != nil {
|
2022-06-22 10:55:31 +00:00
|
|
|
eaclInfo.Session = new(session.Container)
|
2021-12-16 15:26:13 +00:00
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
err := eaclInfo.Session.ReadFromV2(*tokV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid session token: %w", err)
|
|
|
|
}
|
|
|
|
}
|
2021-05-25 16:25:14 +00:00
|
|
|
|
2022-07-22 14:04:37 +00:00
|
|
|
err = s.wrt.PutEACL(eaclInfo)
|
2021-09-08 13:31:05 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return new(container.SetExtendedACLResponseBody), nil
|
2020-08-24 14:07:08 +00:00
|
|
|
}
|
|
|
|
|
2023-04-26 08:24:40 +00:00
|
|
|
func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
2022-05-12 16:37:46 +00:00
|
|
|
idV2 := body.GetContainerID()
|
|
|
|
if idV2 == nil {
|
|
|
|
return nil, errors.New("missing container ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
var id cid.ID
|
|
|
|
|
|
|
|
err := id.ReadFromV2(*idV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid container ID: %w", err)
|
|
|
|
}
|
2020-08-24 14:07:08 +00:00
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
eaclInfo, 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
|
|
|
}
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
var sigV2 refs.Signature
|
|
|
|
eaclInfo.Signature.WriteToV2(&sigV2)
|
2022-05-16 13:15:31 +00:00
|
|
|
|
2022-05-18 15:20:08 +00:00
|
|
|
var tokV2 *sessionV2.Token
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
if eaclInfo.Session != nil {
|
2022-05-18 15:20:08 +00:00
|
|
|
tokV2 = new(sessionV2.Token)
|
|
|
|
|
2022-06-22 10:55:31 +00:00
|
|
|
eaclInfo.Session.WriteToV2(tokV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
res := new(container.GetExtendedACLResponseBody)
|
2022-06-22 10:55:31 +00:00
|
|
|
res.SetEACL(eaclInfo.Value.ToV2())
|
|
|
|
res.SetSignature(&sigV2)
|
2022-05-18 15:20:08 +00:00
|
|
|
res.SetSessionToken(tokV2)
|
2020-09-04 12:18:47 +00:00
|
|
|
|
2020-08-24 14:07:08 +00:00
|
|
|
return res, nil
|
|
|
|
}
|