diff --git a/api/layer/layer.go b/api/layer/layer.go index 70c3c789..2fe863d1 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -3,11 +3,14 @@ package layer import ( "context" "crypto/ecdsa" + "crypto/rand" "fmt" "io" "net/url" "strings" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" + "github.com/nats-io/nats.go" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-s3-gw/api" @@ -541,10 +544,30 @@ func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*data.Obje }) } +func getRandomOID() (*oid.ID, error) { + b := [32]byte{} + if _, err := rand.Read(b[:]); err != nil { + return nil, err + } + + var objID oid.ID + objID.SetSHA256(b) + return &objID, nil +} + // DeleteObject removes all objects with the passed nice name. -func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, settings *data.BucketSettings, obj *VersionedObject) *VersionedObject { - if !isRegularVersion(obj.VersionID) { +func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, _ *data.BucketSettings, obj *VersionedObject) *VersionedObject { + if !isRegularVersion(obj.VersionID) { // version null or empty + randOID, err := getRandomOID() + if err != nil { + obj.Error = fmt.Errorf("couldn't get random oid: %w", err) + return obj + } + obj.DeleteMarkVersion = randOID.EncodeToString() newVersion := &NodeVersion{ + BaseNodeVersion: BaseNodeVersion{ + OID: *randOID, + }, IsDeleteMarker: true, IsUnversioned: obj.VersionID == unversionedObjectVersionID, } diff --git a/api/layer/object.go b/api/layer/object.go index a10adc34..6d828eb1 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -268,59 +268,6 @@ func (n *layer) putLockObject(ctx context.Context, bktInfo *data.BucketInfo, obj return nil } -func updateCRDT2PSetHeaders(header map[string]string, versions *objectVersions, versioningEnabled bool) []oid.ID { - if !versioningEnabled { - header[versionsUnversionedAttr] = "true" - } - - var idsToDeleteArr []oid.ID - if versions.isEmpty() { - return idsToDeleteArr - } - - if !versions.isAddListEmpty() { - header[versionsAddAttr] = versions.getAddHeader() - } - - if versioningEnabled { - versionsDeletedStr := versions.getDelHeader() - // header[versionsDelAttr] can be not empty when deleting specific version - if delAttr := header[versionsDelAttr]; len(delAttr) != 0 { - if len(versionsDeletedStr) != 0 { - header[versionsDelAttr] = versionsDeletedStr + "," + delAttr - } else { - header[versionsDelAttr] = delAttr - } - } else if len(versionsDeletedStr) != 0 { - header[versionsDelAttr] = versionsDeletedStr - } - } else { - versionsDeletedStr := versions.getDelHeader() - - var additionalDel string - for i, del := range versions.unversioned() { - if i != 0 { - additionalDel += "," - } - additionalDel += del.Version() - idsToDeleteArr = append(idsToDeleteArr, del.ID) - } - - if len(additionalDel) != 0 { - if len(versionsDeletedStr) != 0 { - versionsDeletedStr += "," - } - versionsDeletedStr += additionalDel - } - - if len(versionsDeletedStr) != 0 { - header[versionsDelAttr] = versionsDeletedStr - } - } - - return idsToDeleteArr -} - func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.BucketInfo, objectName string) (*data.ObjectInfo, error) { if addr := n.namesCache.Get(bkt.Name + "/" + objectName); addr != nil { if headInfo := n.objCache.Get(*addr); headInfo != nil { @@ -330,6 +277,9 @@ func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke node, err := n.treeService.GetLatestVersion(ctx, &bkt.CID, objectName) if err != nil { + if errors.Is(err, ErrNodeNotFound) { + return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey) + } return nil, err } @@ -410,16 +360,28 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb return objInfo, nil } - var id oid.ID - if err := id.DecodeString(p.VersionID); err != nil { - return nil, apiErrors.GetAPIError(apiErrors.ErrInvalidVersion) + versions, err := n.treeService.GetVersions(ctx, &bkt.CID, p.Object) + if err != nil { + return nil, fmt.Errorf("couldn't get versions: %w", err) } - if headInfo := n.objCache.Get(newAddress(bkt.CID, id)); headInfo != nil { + var foundVersion *NodeVersion + for _, version := range versions { + if version.OID.EncodeToString() == p.VersionID { + foundVersion = version + break + } + } + + if foundVersion == nil { + return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) + } + + if headInfo := n.objCache.Get(newAddress(bkt.CID, foundVersion.OID)); headInfo != nil { return objInfoFromMeta(bkt, headInfo), nil } - meta, err := n.objectHead(ctx, bkt, id) + meta, err := n.objectHead(ctx, bkt, foundVersion.OID) if err != nil { if client.IsErrObjectNotFound(err) { return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) diff --git a/api/layer/system_object.go b/api/layer/system_object.go index c0dcbcee..29dcafb7 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -44,6 +44,9 @@ func (n *layer) HeadSystemObject(ctx context.Context, bkt *data.BucketInfo, objN node, err := n.treeService.GetSystemVersion(ctx, &bkt.CID, objName) if err != nil { + if errorsStd.Is(err, ErrNodeNotFound) { + return nil, errors.GetAPIError(errors.ErrNoSuchKey) + } return nil, err } diff --git a/api/layer/tree_service.go b/api/layer/tree_service.go index 8d6ba8c2..d933b11a 100644 --- a/api/layer/tree_service.go +++ b/api/layer/tree_service.go @@ -31,19 +31,13 @@ type TreeService interface { DeleteBucketCORS(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) GetVersions(ctx context.Context, cnrID *cid.ID, objectName string) ([]*NodeVersion, error) - GetLatestVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error) - GetUnversioned(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error) - AddVersion(ctx context.Context, cnrID *cid.ID, objectName string, newVersion *NodeVersion) error - RemoveVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error AddSystemVersion(ctx context.Context, cnrID *cid.ID, objectName string, newVersion *BaseNodeVersion) error - GetSystemVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*BaseNodeVersion, error) - RemoveSystemVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error } diff --git a/api/layer/versioning.go b/api/layer/versioning.go index 6e46c0e0..2ec793b0 100644 --- a/api/layer/versioning.go +++ b/api/layer/versioning.go @@ -8,8 +8,6 @@ import ( "strings" "github.com/nspcc-dev/neofs-s3-gw/api/data" - "github.com/nspcc-dev/neofs-s3-gw/api/errors" - oid "github.com/nspcc-dev/neofs-sdk-go/object/id" ) type objectVersions struct { @@ -57,11 +55,6 @@ func newObjectVersions(name string) *objectVersions { return &objectVersions{name: name} } -func (v *objectVersions) isAddListEmpty() bool { - v.sort() - return len(v.addList) == 0 -} - func (v *objectVersions) appendVersion(oi *data.ObjectInfo) { delVers := splitVersions(oi.Headers[versionsDelAttr]) v.objects = append(v.objects, oi) @@ -182,23 +175,6 @@ func (v *objectVersions) isEmpty() bool { return v == nil || len(v.objects) == 0 } -func (v *objectVersions) unversioned() []*data.ObjectInfo { - if len(v.objects) == 0 { - return nil - } - - existedVersions := v.existedVersions() - res := make([]*data.ObjectInfo, 0, len(v.objects)) - - for _, version := range v.objects { - if contains(existedVersions, version.Version()) && version.Headers[versionsUnversionedAttr] == "true" { - res = append(res, version) - } - } - - return res -} - func (v *objectVersions) getLast(opts ...VersionOption) *data.ObjectInfo { if v.isEmpty() { return nil @@ -267,22 +243,6 @@ func (v *objectVersions) getAddHeader() string { return strings.Join(v.addList, ",") } -func (v *objectVersions) getDelHeader() string { - return strings.Join(v.delList, ",") -} - -func (v *objectVersions) getVersion(obj oid.ID) *data.ObjectInfo { - strObj := obj.EncodeToString() - for _, version := range v.objects { - if version.Version() == strObj { - if contains(v.delList, strObj) { - return nil - } - return version - } - } - return nil -} func (n *layer) PutBucketVersioning(ctx context.Context, p *PutSettingsParams) (*data.ObjectInfo, error) { metadata := map[string]string{ attrSettingsVersioningEnabled: strconv.FormatBool(p.Settings.VersioningEnabled), @@ -383,27 +343,3 @@ func contains(list []string, elem string) bool { } return false } - -func (n *layer) checkVersionsExist(ctx context.Context, bkt *data.BucketInfo, obj *VersionedObject) (*data.ObjectInfo, error) { - versions, err := n.headVersions(ctx, bkt, obj.Name) - if err != nil { - return nil, err - } - - var version *data.ObjectInfo - if obj.VersionID == unversionedObjectVersionID { - version = versions.getLast(FromUnversioned()) - } else { - var id oid.ID - if err = id.DecodeString(obj.VersionID); err != nil { - return nil, errors.GetAPIError(errors.ErrInvalidVersion) - } - version = versions.getVersion(id) - } - - if version == nil { - return nil, errors.GetAPIError(errors.ErrInvalidVersion) - } - - return version, nil -} diff --git a/api/layer/versioning_test.go b/api/layer/versioning_test.go index 3e875470..b26a8022 100644 --- a/api/layer/versioning_test.go +++ b/api/layer/versioning_test.go @@ -506,108 +506,12 @@ func getTestObjectInfo(id byte, addAttr, delAttr, delMarkAttr string) *data.Obje } } -func getTestUnversionedObjectInfo(id byte, addAttr, delAttr, delMarkAttr string) *data.ObjectInfo { - objInfo := getTestObjectInfo(id, addAttr, delAttr, delMarkAttr) - objInfo.Headers[versionsUnversionedAttr] = "true" - return objInfo -} - func getTestObjectInfoEpoch(epoch uint64, id byte, addAttr, delAttr, delMarkAttr string) *data.ObjectInfo { obj := getTestObjectInfo(id, addAttr, delAttr, delMarkAttr) obj.CreationEpoch = epoch return obj } -func TestUpdateCRDT2PSetHeaders(t *testing.T) { - obj1 := getTestUnversionedObjectInfo(1, "", "", "") - obj2 := getTestUnversionedObjectInfo(2, "", "", "") - obj3 := getTestObjectInfo(3, "", "", "") - obj4 := getTestObjectInfo(4, "", "", "") - - for _, tc := range []struct { - name string - header map[string]string - versions *objectVersions - versioningEnabled bool - expectedHeader map[string]string - expectedIdsToDelete []oid.ID - }{ - { - name: "unversioned save headers", - header: map[string]string{"someKey": "someValue"}, - expectedHeader: map[string]string{"someKey": "someValue", versionsUnversionedAttr: "true"}, - }, - { - name: "unversioned put", - header: map[string]string{}, - versions: &objectVersions{ - objects: []*data.ObjectInfo{obj1}, - }, - expectedHeader: map[string]string{ - versionsAddAttr: obj1.Version(), - versionsDelAttr: obj1.Version(), - versionsUnversionedAttr: "true", - }, - expectedIdsToDelete: []oid.ID{obj1.ID}, - }, - { - name: "unversioned del header", - header: map[string]string{}, - versions: &objectVersions{ - objects: []*data.ObjectInfo{obj2}, - delList: []string{obj1.Version()}, - }, - expectedHeader: map[string]string{ - versionsAddAttr: obj2.Version(), - versionsDelAttr: joinVers(obj1, obj2), - versionsUnversionedAttr: "true", - }, - expectedIdsToDelete: []oid.ID{obj2.ID}, - }, - { - name: "versioned put", - header: map[string]string{}, - versions: &objectVersions{ - objects: []*data.ObjectInfo{obj3}, - }, - versioningEnabled: true, - expectedHeader: map[string]string{versionsAddAttr: obj3.Version()}, - }, - { - name: "versioned del header", - header: map[string]string{versionsDelAttr: obj4.Version()}, - versions: &objectVersions{ - objects: []*data.ObjectInfo{obj4}, - delList: []string{obj3.Version()}, - }, - versioningEnabled: true, - expectedHeader: map[string]string{ - versionsAddAttr: obj4.Version(), - versionsDelAttr: joinVers(obj3, obj4), - }, - }, - { - name: "unversioned put after some version", - header: map[string]string{}, - versions: &objectVersions{ - objects: []*data.ObjectInfo{obj1, obj3}, - }, - expectedHeader: map[string]string{ - versionsAddAttr: joinVers(obj1, obj3), - versionsDelAttr: obj1.Version(), - versionsUnversionedAttr: "true", - }, - expectedIdsToDelete: []oid.ID{obj1.ID}, - }, - } { - t.Run(tc.name, func(t *testing.T) { - idsToDelete := updateCRDT2PSetHeaders(tc.header, tc.versions, tc.versioningEnabled) - require.Equal(t, tc.expectedHeader, tc.header) - require.Equal(t, tc.expectedIdsToDelete, idsToDelete) - }) - } -} - func TestSystemObjectsVersioning(t *testing.T) { cacheConfig := DefaultCachesConfigs(zap.NewExample()) cacheConfig.System.Lifetime = 0 diff --git a/internal/neofs/tree.go b/internal/neofs/tree.go index d5aed7f8..56dde0d0 100644 --- a/internal/neofs/tree.go +++ b/internal/neofs/tree.go @@ -7,8 +7,10 @@ import ( "strconv" "strings" + "github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api/data" "github.com/nspcc-dev/neofs-s3-gw/api/layer" + "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/internal/neofs/services/tree" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -24,7 +26,7 @@ type ( TreeNode struct { ID uint64 - ObjID *oid.ID + ObjID oid.ID TimeStamp uint64 Meta map[string]string } @@ -43,12 +45,12 @@ const ( notifConfFileName = "bucket-notifications" corsFilename = "bucket-cors" - // bucketSystemObjectsTreeID -- ID of a tree with system objects for bucket - // i.e. bucket settings with versioning and lock configuration, cors, notifications - bucketSystemObjectsTreeID = "system-bucket" - + // versionTree -- ID of a tree with object versions. versionTree = "version" - systemTree = "system" + + // systemTree -- ID of a tree with system objects + // i.e. bucket settings with versioning and lock configuration, cors, notifications. + systemTree = "system" separator = "/" ) @@ -69,14 +71,12 @@ func NewTreeClient(addr string) (*TreeClient, error) { } func newTreeNode(nodeInfo *tree.GetNodeByPathResponse_Info) (*TreeNode, error) { - var objID *oid.ID + var objID oid.ID meta := make(map[string]string, len(nodeInfo.GetMeta())) for _, kv := range nodeInfo.GetMeta() { if kv.GetKey() == oidKV { - objID = new(oid.ID) - err := objID.DecodeString(string(kv.GetValue())) - if err != nil { + if err := objID.DecodeString(string(kv.GetValue())); err != nil { return nil, err } continue @@ -110,7 +110,7 @@ func newNodeVersion(node *tree.GetNodeByPathResponse_Info) (*layer.NodeVersion, return &layer.NodeVersion{ BaseNodeVersion: layer.BaseNodeVersion{ ID: node.NodeId, - OID: *treeNode.ObjID, + OID: treeNode.ObjID, }, IsUnversioned: isUnversioned, IsDeleteMarker: isDeleteMarker, @@ -119,8 +119,7 @@ func newNodeVersion(node *tree.GetNodeByPathResponse_Info) (*layer.NodeVersion, func (c *TreeClient) GetSettingsNode(ctx context.Context, cnrID *cid.ID) (*data.BucketSettings, error) { keysToReturn := []string{versioningEnabledKV, lockConfigurationKV} - path := []string{settingsFileName} - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, path, keysToReturn) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{settingsFileName}, keysToReturn) if err != nil { return nil, fmt.Errorf("couldn't get node: %w", err) } @@ -143,8 +142,7 @@ func (c *TreeClient) GetSettingsNode(ctx context.Context, cnrID *cid.ID) (*data. } func (c *TreeClient) PutSettingsNode(ctx context.Context, cnrID *cid.ID, settings *data.BucketSettings) error { - path := []string{settingsFileName} - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, path, []string{}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{settingsFileName}, []string{}) isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) if err != nil && !isErrNotFound { return fmt.Errorf("couldn't get node: %w", err) @@ -153,26 +151,24 @@ func (c *TreeClient) PutSettingsNode(ctx context.Context, cnrID *cid.ID, setting meta := metaFromSettings(settings) if isErrNotFound { - _, err = c.addNode(ctx, cnrID, bucketSystemObjectsTreeID, 0, meta) + _, err = c.addNode(ctx, cnrID, systemTree, 0, meta) return err } - return c.moveNode(ctx, cnrID, bucketSystemObjectsTreeID, node.ID, 0, meta) + return c.moveNode(ctx, cnrID, systemTree, node.ID, 0, meta) } func (c *TreeClient) GetNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) { - path := []string{notifConfFileName} - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, path, []string{oidKV}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{notifConfFileName}, []string{oidKV}) if err != nil { return nil, err } - return node.ObjID, nil + return &node.ObjID, nil } func (c *TreeClient) PutNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, objID *oid.ID) (*oid.ID, error) { - path := []string{notifConfFileName} - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, path, []string{oidKV}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{notifConfFileName}, []string{oidKV}) isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, fmt.Errorf("couldn't get node: %w", err) @@ -183,24 +179,24 @@ func (c *TreeClient) PutNotificationConfigurationNode(ctx context.Context, cnrID meta[oidKV] = objID.EncodeToString() if isErrNotFound { - _, err = c.addNode(ctx, cnrID, bucketSystemObjectsTreeID, 0, meta) + _, err = c.addNode(ctx, cnrID, systemTree, 0, meta) return nil, err } - return node.ObjID, c.moveNode(ctx, cnrID, bucketSystemObjectsTreeID, node.ID, 0, meta) + return &node.ObjID, c.moveNode(ctx, cnrID, systemTree, node.ID, 0, meta) } func (c *TreeClient) GetBucketCORS(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) { - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, []string{corsFilename}, []string{oidKV}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{corsFilename}, []string{oidKV}) if err != nil { return nil, err } - return node.ObjID, nil + return &node.ObjID, nil } func (c *TreeClient) PutBucketCORS(ctx context.Context, cnrID *cid.ID, objID *oid.ID) (*oid.ID, error) { - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, []string{corsFilename}, []string{oidKV}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{corsFilename}, []string{oidKV}) isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, fmt.Errorf("couldn't get node: %w", err) @@ -211,21 +207,21 @@ func (c *TreeClient) PutBucketCORS(ctx context.Context, cnrID *cid.ID, objID *oi meta[oidKV] = objID.EncodeToString() if isErrNotFound { - _, err = c.addNode(ctx, cnrID, bucketSystemObjectsTreeID, 0, meta) + _, err = c.addNode(ctx, cnrID, systemTree, 0, meta) return nil, err } - return node.ObjID, c.moveNode(ctx, cnrID, bucketSystemObjectsTreeID, node.ID, 0, meta) + return &node.ObjID, c.moveNode(ctx, cnrID, systemTree, node.ID, 0, meta) } func (c *TreeClient) DeleteBucketCORS(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) { - node, err := c.getSystemNode(ctx, cnrID, bucketSystemObjectsTreeID, []string{corsFilename}, []string{oidKV}) + node, err := c.getSystemNode(ctx, cnrID, systemTree, []string{corsFilename}, []string{oidKV}) if err != nil && !errors.Is(err, layer.ErrNodeNotFound) { return nil, err } if node != nil { - return node.ObjID, c.removeNode(ctx, cnrID, bucketSystemObjectsTreeID, node.ID) + return &node.ObjID, c.removeNode(ctx, cnrID, systemTree, node.ID) } return nil, nil @@ -262,6 +258,10 @@ func (c *TreeClient) getLatestVersion(ctx context.Context, cnrID *cid.ID, treeID return nil, fmt.Errorf("couldn't get nodes: %w", err) } + if len(nodes) == 0 { + return nil, layer.ErrNodeNotFound + } + return newNodeVersion(nodes[0]) } @@ -352,6 +352,7 @@ func (c *TreeClient) removeVersion(ctx context.Context, cnrID *cid.ID, treeID st ContainerId: []byte(cnrID.EncodeToString()), TreeId: treeID, NodeId: id, + BearerToken: getBearer(ctx), }, } @@ -360,7 +361,7 @@ func (c *TreeClient) removeVersion(ctx context.Context, cnrID *cid.ID, treeID st } func (c *TreeClient) getVersions(ctx context.Context, cnrID *cid.ID, treeID, filepath string, onlyUnversioned bool) ([]*layer.NodeVersion, error) { - keysToReturn := []string{versioningEnabledKV, lockConfigurationKV} + keysToReturn := []string{oidKV, isUnversionedKV, isDeleteMarkerKV} path := strings.Split(filepath, separator) nodes, err := c.getNodes(ctx, cnrID, treeID, fileNameKV, path, keysToReturn, false) if err != nil { @@ -393,6 +394,7 @@ func (c *TreeClient) getParent(ctx context.Context, cnrID *cid.ID, treeID string ContainerId: []byte(cnrID.EncodeToString()), TreeId: treeID, RootId: id, + BearerToken: getBearer(ctx), }, } @@ -423,10 +425,6 @@ func (c *TreeClient) getSystemNode(ctx context.Context, cnrID *cid.ID, treeID st return c.getNode(ctx, cnrID, treeID, systemNameKV, path, meta) } -func (c *TreeClient) getRegularNode(ctx context.Context, cnrID *cid.ID, treeID string, path, meta []string) (*TreeNode, error) { - return c.getNode(ctx, cnrID, treeID, fileNameKV, path, meta) -} - func (c *TreeClient) getNode(ctx context.Context, cnrID *cid.ID, treeID, pathAttr string, path, meta []string) (*TreeNode, error) { nodes, err := c.getNodes(ctx, cnrID, treeID, pathAttr, path, meta, false) if err != nil { @@ -454,6 +452,7 @@ func (c *TreeClient) getNodes(ctx context.Context, cnrID *cid.ID, treeID, pathAt Attributes: meta, PathAttribute: pathAttr, LatestOnly: latestOnly, + BearerToken: getBearer(ctx), }, } @@ -465,6 +464,15 @@ func (c *TreeClient) getNodes(ctx context.Context, cnrID *cid.ID, treeID, pathAt return resp.GetBody().GetNodes(), nil } +func getBearer(ctx context.Context) []byte { + if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil { + if bd.Gate.BearerToken != nil { + return bd.Gate.BearerToken.Marshal() + } + } + return nil +} + func (c *TreeClient) addNode(ctx context.Context, cnrID *cid.ID, treeID string, parent uint64, meta map[string]string) (uint64, error) { request := &tree.AddRequest{ Body: &tree.AddRequest_Body{ @@ -472,6 +480,7 @@ func (c *TreeClient) addNode(ctx context.Context, cnrID *cid.ID, treeID string, TreeId: treeID, ParentId: parent, Meta: metaToKV(meta), + BearerToken: getBearer(ctx), }, } @@ -491,6 +500,7 @@ func (c *TreeClient) addNodeByPath(ctx context.Context, cnrID *cid.ID, treeID st Path: path, Meta: metaToKV(meta), PathAttribute: fileNameKV, + BearerToken: getBearer(ctx), }, } @@ -519,6 +529,7 @@ func (c *TreeClient) removeNode(ctx context.Context, cnrID *cid.ID, treeID strin ContainerId: []byte(cnrID.EncodeToString()), TreeId: treeID, NodeId: nodeID, + BearerToken: getBearer(ctx), }, } _, err := c.service.Remove(ctx, r)