frostfs-node/services/public/object/response.go
alexvanin dadfd90dcd Initial commit
Initial public review release v0.10.0
2020-07-10 17:45:00 +03:00

144 lines
3.1 KiB
Go

package object
import (
"context"
"github.com/nspcc-dev/neofs-api-go/acl"
"github.com/nspcc-dev/neofs-api-go/object"
libacl "github.com/nspcc-dev/neofs-node/lib/acl"
)
type (
serviceResponse interface {
SetEpoch(uint64)
}
responsePreparer interface {
prepareResponse(context.Context, serviceRequest, serviceResponse) error
}
epochResponsePreparer struct {
epochRecv EpochReceiver
}
)
type complexResponsePreparer struct {
items []responsePreparer
}
type aclResponsePreparer struct {
eaclSrc libacl.ExtendedACLSource
aclInfoReceiver aclInfoReceiver
reqActCalc requestActionCalculator
}
type headersFromObject struct {
obj *Object
}
var (
_ responsePreparer = (*epochResponsePreparer)(nil)
)
func (s headersFromObject) getHeaders() (*Object, bool) {
return s.obj, true
}
func (s complexResponsePreparer) prepareResponse(ctx context.Context, req serviceRequest, resp serviceResponse) error {
for i := range s.items {
if err := s.items[i].prepareResponse(ctx, req, resp); err != nil {
return err
}
}
return nil
}
func (s *epochResponsePreparer) prepareResponse(_ context.Context, req serviceRequest, resp serviceResponse) error {
resp.SetEpoch(s.epochRecv.Epoch())
return nil
}
func (s *aclResponsePreparer) prepareResponse(ctx context.Context, req serviceRequest, resp serviceResponse) error {
aclInfo, err := s.aclInfoReceiver.getACLInfo(ctx, req)
if err != nil {
return errAccessDenied
} else if !aclInfo.checkBearer && !aclInfo.checkExtended {
return nil
}
var obj *Object
switch r := resp.(type) {
case *object.GetResponse:
obj = r.GetObject()
case *object.HeadResponse:
obj = r.GetObject()
case interface {
GetObject() *Object
}:
obj = r.GetObject()
}
if obj == nil {
return nil
}
// FIXME: do not check request headers.
// At this stage request is already validated, but action calculator will check it again.
p := requestActionParams{
eaclSrc: s.eaclSrc,
request: req,
objHdrSrc: headersFromObject{
obj: obj,
},
target: aclInfo.target,
}
if aclInfo.checkBearer {
p.eaclSrc = eaclFromBearer{
bearer: req.GetBearerToken(),
}
}
if action := s.reqActCalc.calculateRequestAction(ctx, p); action != acl.ActionAllow {
return errAccessDenied
}
return nil
}
func makeDeleteResponse() *object.DeleteResponse {
return new(object.DeleteResponse)
}
func makeRangeHashResponse(v []Hash) *GetRangeHashResponse {
return &GetRangeHashResponse{Hashes: v}
}
func makeRangeResponse(v []byte) *GetRangeResponse {
return &GetRangeResponse{Fragment: v}
}
func makeSearchResponse(v []Address) *object.SearchResponse {
return &object.SearchResponse{Addresses: v}
}
func makeHeadResponse(v *Object) *object.HeadResponse {
return &object.HeadResponse{Object: v}
}
func makePutResponse(v Address) *object.PutResponse {
return &object.PutResponse{Address: v}
}
func makeGetHeaderResponse(v *Object) *object.GetResponse {
return &object.GetResponse{R: &object.GetResponse_Object{Object: v}}
}
func makeGetChunkResponse(v []byte) *object.GetResponse {
return &object.GetResponse{R: &object.GetResponse_Chunk{Chunk: v}}
}