parent
c7c570fd10
commit
dc1926f9c6
18 changed files with 1837 additions and 126 deletions
|
@ -117,10 +117,11 @@ func runTests(ctx context.Context, t *testing.T, key *keys.PrivateKey, version s
|
||||||
t.Run("rest put object "+version, func(t *testing.T) { restObjectPut(ctx, t, clientPool, cnrID) })
|
t.Run("rest put object "+version, func(t *testing.T) { restObjectPut(ctx, t, clientPool, cnrID) })
|
||||||
t.Run("rest get object "+version, func(t *testing.T) { restObjectGet(ctx, t, clientPool, cnrID) })
|
t.Run("rest get object "+version, func(t *testing.T) { restObjectGet(ctx, t, clientPool, cnrID) })
|
||||||
t.Run("rest delete object "+version, func(t *testing.T) { restObjectDelete(ctx, t, clientPool, cnrID) })
|
t.Run("rest delete object "+version, func(t *testing.T) { restObjectDelete(ctx, t, clientPool, cnrID) })
|
||||||
|
t.Run("rest search objects "+version, func(t *testing.T) { restObjectsSearch(ctx, t, clientPool, cnrID) })
|
||||||
|
|
||||||
t.Run("rest put container "+version, func(t *testing.T) { restContainerPut(ctx, t, clientPool) })
|
t.Run("rest put container "+version, func(t *testing.T) { restContainerPut(ctx, t, clientPool) })
|
||||||
t.Run("rest get container "+version, func(t *testing.T) { restContainerGet(ctx, t, clientPool, cnrID) })
|
t.Run("rest get container "+version, func(t *testing.T) { restContainerGet(ctx, t, clientPool, cnrID) })
|
||||||
//t.Run("rest delete container "+version, func(t *testing.T) { restContainerDelete(ctx, t, clientPool) })
|
t.Run("rest delete container "+version, func(t *testing.T) { restContainerDelete(ctx, t, clientPool) })
|
||||||
t.Run("rest put container eacl "+version, func(t *testing.T) { restContainerEACLPut(ctx, t, clientPool) })
|
t.Run("rest put container eacl "+version, func(t *testing.T) { restContainerEACLPut(ctx, t, clientPool) })
|
||||||
t.Run("rest get container eacl "+version, func(t *testing.T) { restContainerEACLGet(ctx, t, clientPool, cnrID) })
|
t.Run("rest get container eacl "+version, func(t *testing.T) { restContainerEACLGet(ctx, t, clientPool, cnrID) })
|
||||||
t.Run("rest list containers "+version, func(t *testing.T) { restContainerList(ctx, t, clientPool, cnrID) })
|
t.Run("rest list containers "+version, func(t *testing.T) { restContainerList(ctx, t, clientPool, cnrID) })
|
||||||
|
@ -243,7 +244,7 @@ func restObjectPut(ctx context.Context, t *testing.T, clientPool *pool.Pool, cnr
|
||||||
prepareCommonHeaders(request.Header, bearerToken)
|
prepareCommonHeaders(request.Header, bearerToken)
|
||||||
request.Header.Add("X-Attribute-"+attrKey, attrValue)
|
request.Header.Add("X-Attribute-"+attrKey, attrValue)
|
||||||
|
|
||||||
addr := &operations.PutObjectOKBody{}
|
addr := &models.Address{}
|
||||||
doRequest(t, httpClient, request, http.StatusOK, addr)
|
doRequest(t, httpClient, request, http.StatusOK, addr)
|
||||||
|
|
||||||
var CID cid.ID
|
var CID cid.ID
|
||||||
|
@ -352,6 +353,75 @@ func restObjectDelete(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *ci
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func restObjectsSearch(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *cid.ID) {
|
||||||
|
userKey, userValue := "User-Attribute", "user-attribute-value"
|
||||||
|
objectName := "object-name"
|
||||||
|
headers := map[string]string{
|
||||||
|
object.AttributeFileName: objectName,
|
||||||
|
userKey: userValue,
|
||||||
|
}
|
||||||
|
objID := createObject(ctx, t, p, cnrID, headers, []byte("some content"))
|
||||||
|
headers[userKey] = "dummy"
|
||||||
|
_ = createObject(ctx, t, p, cnrID, headers, []byte("some content"))
|
||||||
|
|
||||||
|
bearer := &models.Bearer{
|
||||||
|
Object: []*models.Record{
|
||||||
|
{
|
||||||
|
Operation: models.NewOperation(models.OperationSEARCH),
|
||||||
|
Action: models.NewAction(models.ActionALLOW),
|
||||||
|
Filters: []*models.Filter{},
|
||||||
|
Targets: []*models.Target{{Role: models.NewRole(models.RoleOTHERS), Keys: []string{}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Operation: models.NewOperation(models.OperationHEAD),
|
||||||
|
Action: models.NewAction(models.ActionALLOW),
|
||||||
|
Filters: []*models.Filter{},
|
||||||
|
Targets: []*models.Target{{Role: models.NewRole(models.RoleOTHERS), Keys: []string{}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Operation: models.NewOperation(models.OperationGET),
|
||||||
|
Action: models.NewAction(models.ActionALLOW),
|
||||||
|
Filters: []*models.Filter{},
|
||||||
|
Targets: []*models.Target{{Role: models.NewRole(models.RoleOTHERS), Keys: []string{}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := defaultHTTPClient()
|
||||||
|
bearerToken := makeAuthObjectTokenRequest(ctx, t, bearer, httpClient)
|
||||||
|
|
||||||
|
search := &models.SearchFilters{
|
||||||
|
Filters: []*models.SearchFilter{
|
||||||
|
{
|
||||||
|
Key: handlers.NewString(userKey),
|
||||||
|
Match: models.NewSearchMatch(models.SearchMatchMatchStringEqual),
|
||||||
|
Value: handlers.NewString(userValue),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := json.Marshal(search)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Add(walletConnectQuery, strconv.FormatBool(useWalletConnect))
|
||||||
|
|
||||||
|
request, err := http.NewRequest(http.MethodPost, testHost+"/v1/objects/"+cnrID.String()+"/search?"+query.Encode(), bytes.NewReader(body))
|
||||||
|
require.NoError(t, err)
|
||||||
|
prepareCommonHeaders(request.Header, bearerToken)
|
||||||
|
|
||||||
|
resp := &models.ObjectList{}
|
||||||
|
doRequest(t, httpClient, request, http.StatusOK, resp)
|
||||||
|
|
||||||
|
require.Equal(t, 1, int(*resp.Size))
|
||||||
|
require.Len(t, resp.Objects, 1)
|
||||||
|
|
||||||
|
objBaseInfo := resp.Objects[0]
|
||||||
|
require.Equal(t, cnrID.String(), *objBaseInfo.Address.ContainerID)
|
||||||
|
require.Equal(t, objID.String(), *objBaseInfo.Address.ObjectID)
|
||||||
|
require.Equal(t, objectName, objBaseInfo.Name)
|
||||||
|
}
|
||||||
|
|
||||||
func doRequest(t *testing.T, httpClient *http.Client, request *http.Request, expectedCode int, model interface{}) {
|
func doRequest(t *testing.T, httpClient *http.Client, request *http.Request, expectedCode int, model interface{}) {
|
||||||
resp, err := httpClient.Do(request)
|
resp, err := httpClient.Do(request)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
89
gen/models/address.go
Normal file
89
gen/models/address.go
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Address address
|
||||||
|
// Example: {"containerId":"5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv","objectId":"8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"}
|
||||||
|
//
|
||||||
|
// swagger:model Address
|
||||||
|
type Address struct {
|
||||||
|
|
||||||
|
// container Id
|
||||||
|
// Required: true
|
||||||
|
ContainerID *string `json:"containerId"`
|
||||||
|
|
||||||
|
// object Id
|
||||||
|
// Required: true
|
||||||
|
ObjectID *string `json:"objectId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this address
|
||||||
|
func (m *Address) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateContainerID(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.validateObjectID(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Address) validateContainerID(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("containerId", "body", m.ContainerID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Address) validateObjectID(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("objectId", "body", m.ObjectID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validates this address based on context it is used
|
||||||
|
func (m *Address) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *Address) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *Address) UnmarshalBinary(b []byte) error {
|
||||||
|
var res Address
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
110
gen/models/object_base_info.go
Normal file
110
gen/models/object_base_info.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjectBaseInfo object base info
|
||||||
|
//
|
||||||
|
// swagger:model ObjectBaseInfo
|
||||||
|
type ObjectBaseInfo struct {
|
||||||
|
|
||||||
|
// address
|
||||||
|
// Required: true
|
||||||
|
Address *Address `json:"address"`
|
||||||
|
|
||||||
|
// name
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this object base info
|
||||||
|
func (m *ObjectBaseInfo) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateAddress(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ObjectBaseInfo) validateAddress(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("address", "body", m.Address); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Address != nil {
|
||||||
|
if err := m.Address.Validate(formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("address")
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("address")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validate this object base info based on the context it is used
|
||||||
|
func (m *ObjectBaseInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.contextValidateAddress(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ObjectBaseInfo) contextValidateAddress(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if m.Address != nil {
|
||||||
|
if err := m.Address.ContextValidate(ctx, formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("address")
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("address")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *ObjectBaseInfo) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *ObjectBaseInfo) UnmarshalBinary(b []byte) error {
|
||||||
|
var res ObjectBaseInfo
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
136
gen/models/object_list.go
Normal file
136
gen/models/object_list.go
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjectList object list
|
||||||
|
//
|
||||||
|
// swagger:model ObjectList
|
||||||
|
type ObjectList struct {
|
||||||
|
|
||||||
|
// objects
|
||||||
|
// Required: true
|
||||||
|
Objects []*ObjectBaseInfo `json:"objects"`
|
||||||
|
|
||||||
|
// size
|
||||||
|
// Required: true
|
||||||
|
Size *int64 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this object list
|
||||||
|
func (m *ObjectList) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateObjects(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.validateSize(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ObjectList) validateObjects(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("objects", "body", m.Objects); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(m.Objects); i++ {
|
||||||
|
if swag.IsZero(m.Objects[i]) { // not required
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Objects[i] != nil {
|
||||||
|
if err := m.Objects[i].Validate(formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("objects" + "." + strconv.Itoa(i))
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("objects" + "." + strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ObjectList) validateSize(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("size", "body", m.Size); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validate this object list based on the context it is used
|
||||||
|
func (m *ObjectList) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.contextValidateObjects(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ObjectList) contextValidateObjects(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
for i := 0; i < len(m.Objects); i++ {
|
||||||
|
|
||||||
|
if m.Objects[i] != nil {
|
||||||
|
if err := m.Objects[i].ContextValidate(ctx, formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("objects" + "." + strconv.Itoa(i))
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("objects" + "." + strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *ObjectList) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *ObjectList) UnmarshalBinary(b []byte) error {
|
||||||
|
var res ObjectList
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
145
gen/models/search_filter.go
Normal file
145
gen/models/search_filter.go
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SearchFilter search filter
|
||||||
|
//
|
||||||
|
// swagger:model SearchFilter
|
||||||
|
type SearchFilter struct {
|
||||||
|
|
||||||
|
// key
|
||||||
|
// Required: true
|
||||||
|
Key *string `json:"key"`
|
||||||
|
|
||||||
|
// match
|
||||||
|
// Required: true
|
||||||
|
Match *SearchMatch `json:"match"`
|
||||||
|
|
||||||
|
// value
|
||||||
|
// Required: true
|
||||||
|
Value *string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this search filter
|
||||||
|
func (m *SearchFilter) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateKey(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.validateMatch(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.validateValue(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilter) validateKey(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("key", "body", m.Key); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilter) validateMatch(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("match", "body", m.Match); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validate.Required("match", "body", m.Match); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Match != nil {
|
||||||
|
if err := m.Match.Validate(formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("match")
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("match")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilter) validateValue(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("value", "body", m.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validate this search filter based on the context it is used
|
||||||
|
func (m *SearchFilter) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.contextValidateMatch(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilter) contextValidateMatch(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if m.Match != nil {
|
||||||
|
if err := m.Match.ContextValidate(ctx, formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("match")
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("match")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *SearchFilter) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *SearchFilter) UnmarshalBinary(b []byte) error {
|
||||||
|
var res SearchFilter
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
119
gen/models/search_filters.go
Normal file
119
gen/models/search_filters.go
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SearchFilters search filters
|
||||||
|
//
|
||||||
|
// swagger:model SearchFilters
|
||||||
|
type SearchFilters struct {
|
||||||
|
|
||||||
|
// filters
|
||||||
|
// Required: true
|
||||||
|
Filters []*SearchFilter `json:"filters"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this search filters
|
||||||
|
func (m *SearchFilters) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateFilters(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilters) validateFilters(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("filters", "body", m.Filters); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(m.Filters); i++ {
|
||||||
|
if swag.IsZero(m.Filters[i]) { // not required
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Filters[i] != nil {
|
||||||
|
if err := m.Filters[i].Validate(formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("filters" + "." + strconv.Itoa(i))
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("filters" + "." + strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validate this search filters based on the context it is used
|
||||||
|
func (m *SearchFilters) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.contextValidateFilters(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SearchFilters) contextValidateFilters(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
for i := 0; i < len(m.Filters); i++ {
|
||||||
|
|
||||||
|
if m.Filters[i] != nil {
|
||||||
|
if err := m.Filters[i].ContextValidate(ctx, formats); err != nil {
|
||||||
|
if ve, ok := err.(*errors.Validation); ok {
|
||||||
|
return ve.ValidateName("filters" + "." + strconv.Itoa(i))
|
||||||
|
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||||
|
return ce.ValidateName("filters" + "." + strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *SearchFilters) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *SearchFilters) UnmarshalBinary(b []byte) error {
|
||||||
|
var res SearchFilters
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
84
gen/models/search_match.go
Normal file
84
gen/models/search_match.go
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SearchMatch search match
|
||||||
|
//
|
||||||
|
// swagger:model SearchMatch
|
||||||
|
type SearchMatch string
|
||||||
|
|
||||||
|
func NewSearchMatch(value SearchMatch) *SearchMatch {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointer returns a pointer to a freshly-allocated SearchMatch.
|
||||||
|
func (m SearchMatch) Pointer() *SearchMatch {
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// SearchMatchMatchStringEqual captures enum value "MatchStringEqual"
|
||||||
|
SearchMatchMatchStringEqual SearchMatch = "MatchStringEqual"
|
||||||
|
|
||||||
|
// SearchMatchMatchStringNotEqual captures enum value "MatchStringNotEqual"
|
||||||
|
SearchMatchMatchStringNotEqual SearchMatch = "MatchStringNotEqual"
|
||||||
|
|
||||||
|
// SearchMatchMatchNotPresent captures enum value "MatchNotPresent"
|
||||||
|
SearchMatchMatchNotPresent SearchMatch = "MatchNotPresent"
|
||||||
|
|
||||||
|
// SearchMatchMatchCommonPrefix captures enum value "MatchCommonPrefix"
|
||||||
|
SearchMatchMatchCommonPrefix SearchMatch = "MatchCommonPrefix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// for schema
|
||||||
|
var searchMatchEnum []interface{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var res []SearchMatch
|
||||||
|
if err := json.Unmarshal([]byte(`["MatchStringEqual","MatchStringNotEqual","MatchNotPresent","MatchCommonPrefix"]`), &res); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, v := range res {
|
||||||
|
searchMatchEnum = append(searchMatchEnum, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m SearchMatch) validateSearchMatchEnum(path, location string, value SearchMatch) error {
|
||||||
|
if err := validate.EnumCase(path, location, value, searchMatchEnum, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this search match
|
||||||
|
func (m SearchMatch) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
// value enum
|
||||||
|
if err := m.validateSearchMatchEnum("", "body", m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validates this search match based on context it is used
|
||||||
|
func (m SearchMatch) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -368,23 +368,7 @@ func init() {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Address of uploaded objects",
|
"description": "Address of uploaded objects",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/definitions/Address"
|
||||||
"required": [
|
|
||||||
"objectId",
|
|
||||||
"containerId"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"containerId": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"objectId": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"example": {
|
|
||||||
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
|
|
||||||
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -407,6 +391,67 @@ func init() {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"/objects/{containerId}/search": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Search objects by filters",
|
||||||
|
"operationId": "searchObjects",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"default": 0,
|
||||||
|
"description": "The number of containers to skip before starting to collect the result set.",
|
||||||
|
"name": "offset",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maximum": 10000,
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer",
|
||||||
|
"default": 100,
|
||||||
|
"description": "The numbers of containers to return.",
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Filters to search objects",
|
||||||
|
"name": "searchFilters",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/SearchFilters"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of objects",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ObjectList"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureParam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureKeyParam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureScheme"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/containerId"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"/objects/{containerId}/{objectId}": {
|
"/objects/{containerId}/{objectId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Get object info by address and",
|
"summary": "Get object info by address and",
|
||||||
|
@ -468,6 +513,25 @@ func init() {
|
||||||
"DENY"
|
"DENY"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Address": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"containerId",
|
||||||
|
"objectId"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"containerId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"objectId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
|
||||||
|
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Attribute": {
|
"Attribute": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -645,6 +709,20 @@ func init() {
|
||||||
"STRING_NOT_EQUAL"
|
"STRING_NOT_EQUAL"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"ObjectBaseInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"address"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"address": {
|
||||||
|
"$ref": "#/definitions/Address"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ObjectInfo": {
|
"ObjectInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -686,6 +764,24 @@ func init() {
|
||||||
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
|
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ObjectList": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"size",
|
||||||
|
"objects"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"objects": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ObjectBaseInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Operation": {
|
"Operation": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
@ -763,6 +859,48 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"SearchFilter": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"key",
|
||||||
|
"value",
|
||||||
|
"match"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"match": {
|
||||||
|
"$ref": "#/definitions/SearchMatch"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SearchFilters": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"filters"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/SearchFilter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SearchMatch": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"MatchStringEqual",
|
||||||
|
"MatchStringNotEqual",
|
||||||
|
"MatchNotPresent",
|
||||||
|
"MatchCommonPrefix"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Target": {
|
"Target": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -1279,23 +1417,7 @@ func init() {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Address of uploaded objects",
|
"description": "Address of uploaded objects",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/definitions/Address"
|
||||||
"required": [
|
|
||||||
"objectId",
|
|
||||||
"containerId"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"containerId": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"objectId": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"example": {
|
|
||||||
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
|
|
||||||
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -1330,6 +1452,84 @@ func init() {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"/objects/{containerId}/search": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Search objects by filters",
|
||||||
|
"operationId": "searchObjects",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"minimum": 0,
|
||||||
|
"type": "integer",
|
||||||
|
"default": 0,
|
||||||
|
"description": "The number of containers to skip before starting to collect the result set.",
|
||||||
|
"name": "offset",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maximum": 10000,
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer",
|
||||||
|
"default": 100,
|
||||||
|
"description": "The numbers of containers to return.",
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Filters to search objects",
|
||||||
|
"name": "searchFilters",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/SearchFilters"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of objects",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ObjectList"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Base64 encoded signature for bearer token",
|
||||||
|
"name": "X-Bearer-Signature",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Hex encoded the public part of the key that signed the bearer token",
|
||||||
|
"name": "X-Bearer-Signature-Key",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Use wallect connect signature scheme or not",
|
||||||
|
"name": "walletConnect",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Base58 encoded container id",
|
||||||
|
"name": "containerId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"/objects/{containerId}/{objectId}": {
|
"/objects/{containerId}/{objectId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Get object info by address and",
|
"summary": "Get object info by address and",
|
||||||
|
@ -1411,6 +1611,25 @@ func init() {
|
||||||
"DENY"
|
"DENY"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Address": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"containerId",
|
||||||
|
"objectId"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"containerId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"objectId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
|
||||||
|
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Attribute": {
|
"Attribute": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -1588,6 +1807,20 @@ func init() {
|
||||||
"STRING_NOT_EQUAL"
|
"STRING_NOT_EQUAL"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"ObjectBaseInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"address"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"address": {
|
||||||
|
"$ref": "#/definitions/Address"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ObjectInfo": {
|
"ObjectInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -1629,6 +1862,24 @@ func init() {
|
||||||
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
|
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ObjectList": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"size",
|
||||||
|
"objects"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"objects": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ObjectBaseInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Operation": {
|
"Operation": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
@ -1706,6 +1957,48 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"SearchFilter": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"key",
|
||||||
|
"value",
|
||||||
|
"match"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"match": {
|
||||||
|
"$ref": "#/definitions/SearchMatch"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SearchFilters": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"filters"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/SearchFilter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SearchMatch": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"MatchStringEqual",
|
||||||
|
"MatchStringNotEqual",
|
||||||
|
"MatchNotPresent",
|
||||||
|
"MatchCommonPrefix"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Target": {
|
"Target": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|
|
@ -74,6 +74,9 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI {
|
||||||
PutObjectHandler: PutObjectHandlerFunc(func(params PutObjectParams, principal *models.Principal) middleware.Responder {
|
PutObjectHandler: PutObjectHandlerFunc(func(params PutObjectParams, principal *models.Principal) middleware.Responder {
|
||||||
return middleware.NotImplemented("operation PutObject has not yet been implemented")
|
return middleware.NotImplemented("operation PutObject has not yet been implemented")
|
||||||
}),
|
}),
|
||||||
|
SearchObjectsHandler: SearchObjectsHandlerFunc(func(params SearchObjectsParams, principal *models.Principal) middleware.Responder {
|
||||||
|
return middleware.NotImplemented("operation SearchObjects has not yet been implemented")
|
||||||
|
}),
|
||||||
|
|
||||||
// Applies when the "Authorization" header is set
|
// Applies when the "Authorization" header is set
|
||||||
BearerAuthAuth: func(token string) (*models.Principal, error) {
|
BearerAuthAuth: func(token string) (*models.Principal, error) {
|
||||||
|
@ -144,6 +147,8 @@ type NeofsRestGwAPI struct {
|
||||||
PutContainerEACLHandler PutContainerEACLHandler
|
PutContainerEACLHandler PutContainerEACLHandler
|
||||||
// PutObjectHandler sets the operation handler for the put object operation
|
// PutObjectHandler sets the operation handler for the put object operation
|
||||||
PutObjectHandler PutObjectHandler
|
PutObjectHandler PutObjectHandler
|
||||||
|
// SearchObjectsHandler sets the operation handler for the search objects operation
|
||||||
|
SearchObjectsHandler SearchObjectsHandler
|
||||||
|
|
||||||
// ServeError is called when an error is received, there is a default handler
|
// ServeError is called when an error is received, there is a default handler
|
||||||
// but you can set your own with this
|
// but you can set your own with this
|
||||||
|
@ -255,6 +260,9 @@ func (o *NeofsRestGwAPI) Validate() error {
|
||||||
if o.PutObjectHandler == nil {
|
if o.PutObjectHandler == nil {
|
||||||
unregistered = append(unregistered, "PutObjectHandler")
|
unregistered = append(unregistered, "PutObjectHandler")
|
||||||
}
|
}
|
||||||
|
if o.SearchObjectsHandler == nil {
|
||||||
|
unregistered = append(unregistered, "SearchObjectsHandler")
|
||||||
|
}
|
||||||
|
|
||||||
if len(unregistered) > 0 {
|
if len(unregistered) > 0 {
|
||||||
return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", "))
|
return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", "))
|
||||||
|
@ -394,6 +402,10 @@ func (o *NeofsRestGwAPI) initHandlerCache() {
|
||||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||||
}
|
}
|
||||||
o.handlers["PUT"]["/objects"] = NewPutObject(o.context, o.PutObjectHandler)
|
o.handlers["PUT"]["/objects"] = NewPutObject(o.context, o.PutObjectHandler)
|
||||||
|
if o.handlers["POST"] == nil {
|
||||||
|
o.handlers["POST"] = make(map[string]http.Handler)
|
||||||
|
}
|
||||||
|
o.handlers["POST"]["/objects/{containerId}/search"] = NewSearchObjects(o.context, o.SearchObjectsHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve creates a http handler to serve the API over HTTP
|
// Serve creates a http handler to serve the API over HTTP
|
||||||
|
|
|
@ -151,77 +151,3 @@ func (o *PutObjectBody) UnmarshalBinary(b []byte) error {
|
||||||
*o = res
|
*o = res
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectOKBody put object o k body
|
|
||||||
// Example: {"containerId":"5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv","objectId":"8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd"}
|
|
||||||
//
|
|
||||||
// swagger:model PutObjectOKBody
|
|
||||||
type PutObjectOKBody struct {
|
|
||||||
|
|
||||||
// container Id
|
|
||||||
// Required: true
|
|
||||||
ContainerID *string `json:"containerId"`
|
|
||||||
|
|
||||||
// object Id
|
|
||||||
// Required: true
|
|
||||||
ObjectID *string `json:"objectId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate validates this put object o k body
|
|
||||||
func (o *PutObjectOKBody) Validate(formats strfmt.Registry) error {
|
|
||||||
var res []error
|
|
||||||
|
|
||||||
if err := o.validateContainerID(formats); err != nil {
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := o.validateObjectID(formats); err != nil {
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *PutObjectOKBody) validateContainerID(formats strfmt.Registry) error {
|
|
||||||
|
|
||||||
if err := validate.Required("putObjectOK"+"."+"containerId", "body", o.ContainerID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *PutObjectOKBody) validateObjectID(formats strfmt.Registry) error {
|
|
||||||
|
|
||||||
if err := validate.Required("putObjectOK"+"."+"objectId", "body", o.ObjectID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContextValidate validates this put object o k body based on context it is used
|
|
||||||
func (o *PutObjectOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary interface implementation
|
|
||||||
func (o *PutObjectOKBody) MarshalBinary() ([]byte, error) {
|
|
||||||
if o == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return swag.WriteJSON(o)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary interface implementation
|
|
||||||
func (o *PutObjectOKBody) UnmarshalBinary(b []byte) error {
|
|
||||||
var res PutObjectOKBody
|
|
||||||
if err := swag.ReadJSON(b, &res); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*o = res
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ type PutObjectOK struct {
|
||||||
/*
|
/*
|
||||||
In: Body
|
In: Body
|
||||||
*/
|
*/
|
||||||
Payload *PutObjectOKBody `json:"body,omitempty"`
|
Payload *models.Address `json:"body,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPutObjectOK creates PutObjectOK with default headers values
|
// NewPutObjectOK creates PutObjectOK with default headers values
|
||||||
|
@ -35,13 +35,13 @@ func NewPutObjectOK() *PutObjectOK {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithPayload adds the payload to the put object o k response
|
// WithPayload adds the payload to the put object o k response
|
||||||
func (o *PutObjectOK) WithPayload(payload *PutObjectOKBody) *PutObjectOK {
|
func (o *PutObjectOK) WithPayload(payload *models.Address) *PutObjectOK {
|
||||||
o.Payload = payload
|
o.Payload = payload
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPayload sets the payload to the put object o k response
|
// SetPayload sets the payload to the put object o k response
|
||||||
func (o *PutObjectOK) SetPayload(payload *PutObjectOKBody) {
|
func (o *PutObjectOK) SetPayload(payload *models.Address) {
|
||||||
o.Payload = payload
|
o.Payload = payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
71
gen/restapi/operations/search_objects.go
Normal file
71
gen/restapi/operations/search_objects.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package operations
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-openapi/runtime/middleware"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SearchObjectsHandlerFunc turns a function with the right signature into a search objects handler
|
||||||
|
type SearchObjectsHandlerFunc func(SearchObjectsParams, *models.Principal) middleware.Responder
|
||||||
|
|
||||||
|
// Handle executing the request and returning a response
|
||||||
|
func (fn SearchObjectsHandlerFunc) Handle(params SearchObjectsParams, principal *models.Principal) middleware.Responder {
|
||||||
|
return fn(params, principal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchObjectsHandler interface for that can handle valid search objects params
|
||||||
|
type SearchObjectsHandler interface {
|
||||||
|
Handle(SearchObjectsParams, *models.Principal) middleware.Responder
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSearchObjects creates a new http.Handler for the search objects operation
|
||||||
|
func NewSearchObjects(ctx *middleware.Context, handler SearchObjectsHandler) *SearchObjects {
|
||||||
|
return &SearchObjects{Context: ctx, Handler: handler}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SearchObjects swagger:route POST /objects/{containerId}/search searchObjects
|
||||||
|
|
||||||
|
Search objects by filters
|
||||||
|
|
||||||
|
*/
|
||||||
|
type SearchObjects struct {
|
||||||
|
Context *middleware.Context
|
||||||
|
Handler SearchObjectsHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SearchObjects) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||||
|
if rCtx != nil {
|
||||||
|
*r = *rCtx
|
||||||
|
}
|
||||||
|
var Params = NewSearchObjectsParams()
|
||||||
|
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||||
|
if err != nil {
|
||||||
|
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if aCtx != nil {
|
||||||
|
*r = *aCtx
|
||||||
|
}
|
||||||
|
var principal *models.Principal
|
||||||
|
if uprinc != nil {
|
||||||
|
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||||
|
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||||
|
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||||
|
|
||||||
|
}
|
322
gen/restapi/operations/search_objects_parameters.go
Normal file
322
gen/restapi/operations/search_objects_parameters.go
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package operations
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
"github.com/go-openapi/runtime/middleware"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSearchObjectsParams creates a new SearchObjectsParams object
|
||||||
|
// with the default values initialized.
|
||||||
|
func NewSearchObjectsParams() SearchObjectsParams {
|
||||||
|
|
||||||
|
var (
|
||||||
|
// initialize parameters with default values
|
||||||
|
|
||||||
|
limitDefault = int64(100)
|
||||||
|
offsetDefault = int64(0)
|
||||||
|
|
||||||
|
walletConnectDefault = bool(false)
|
||||||
|
)
|
||||||
|
|
||||||
|
return SearchObjectsParams{
|
||||||
|
Limit: &limitDefault,
|
||||||
|
|
||||||
|
Offset: &offsetDefault,
|
||||||
|
|
||||||
|
WalletConnect: &walletConnectDefault,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchObjectsParams contains all the bound params for the search objects operation
|
||||||
|
// typically these are obtained from a http.Request
|
||||||
|
//
|
||||||
|
// swagger:parameters searchObjects
|
||||||
|
type SearchObjectsParams struct {
|
||||||
|
|
||||||
|
// HTTP Request Object
|
||||||
|
HTTPRequest *http.Request `json:"-"`
|
||||||
|
|
||||||
|
/*Base64 encoded signature for bearer token
|
||||||
|
Required: true
|
||||||
|
In: header
|
||||||
|
*/
|
||||||
|
XBearerSignature string
|
||||||
|
/*Hex encoded the public part of the key that signed the bearer token
|
||||||
|
Required: true
|
||||||
|
In: header
|
||||||
|
*/
|
||||||
|
XBearerSignatureKey string
|
||||||
|
/*Base58 encoded container id
|
||||||
|
Required: true
|
||||||
|
In: path
|
||||||
|
*/
|
||||||
|
ContainerID string
|
||||||
|
/*The numbers of containers to return.
|
||||||
|
Maximum: 10000
|
||||||
|
Minimum: 1
|
||||||
|
In: query
|
||||||
|
Default: 100
|
||||||
|
*/
|
||||||
|
Limit *int64
|
||||||
|
/*The number of containers to skip before starting to collect the result set.
|
||||||
|
Minimum: 0
|
||||||
|
In: query
|
||||||
|
Default: 0
|
||||||
|
*/
|
||||||
|
Offset *int64
|
||||||
|
/*Filters to search objects
|
||||||
|
Required: true
|
||||||
|
In: body
|
||||||
|
*/
|
||||||
|
SearchFilters *models.SearchFilters
|
||||||
|
/*Use wallect connect signature scheme or not
|
||||||
|
In: query
|
||||||
|
Default: false
|
||||||
|
*/
|
||||||
|
WalletConnect *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||||
|
// for simple values it will use straight method calls.
|
||||||
|
//
|
||||||
|
// To ensure default values, the struct must have been initialized with NewSearchObjectsParams() beforehand.
|
||||||
|
func (o *SearchObjectsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
o.HTTPRequest = r
|
||||||
|
|
||||||
|
qs := runtime.Values(r.URL.Query())
|
||||||
|
|
||||||
|
if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature")], true, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rContainerID, rhkContainerID, _ := route.Params.GetOK("containerId")
|
||||||
|
if err := o.bindContainerID(rContainerID, rhkContainerID, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
qLimit, qhkLimit, _ := qs.GetOK("limit")
|
||||||
|
if err := o.bindLimit(qLimit, qhkLimit, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
qOffset, qhkOffset, _ := qs.GetOK("offset")
|
||||||
|
if err := o.bindOffset(qOffset, qhkOffset, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.HasBody(r) {
|
||||||
|
defer r.Body.Close()
|
||||||
|
var body models.SearchFilters
|
||||||
|
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
res = append(res, errors.Required("searchFilters", "body", ""))
|
||||||
|
} else {
|
||||||
|
res = append(res, errors.NewParseError("searchFilters", "body", "", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// validate body object
|
||||||
|
if err := body.Validate(route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := validate.WithOperationRequest(context.Background())
|
||||||
|
if err := body.ContextValidate(ctx, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) == 0 {
|
||||||
|
o.SearchFilters = &body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = append(res, errors.Required("searchFilters", "body", ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
qWalletConnect, qhkWalletConnect, _ := qs.GetOK("walletConnect")
|
||||||
|
if err := o.bindWalletConnect(qWalletConnect, qhkWalletConnect, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindXBearerSignature binds and validates parameter XBearerSignature from header.
|
||||||
|
func (o *SearchObjectsParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
if !hasKey {
|
||||||
|
return errors.Required("X-Bearer-Signature", "header", rawData)
|
||||||
|
}
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: true
|
||||||
|
|
||||||
|
if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.XBearerSignature = raw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header.
|
||||||
|
func (o *SearchObjectsParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
if !hasKey {
|
||||||
|
return errors.Required("X-Bearer-Signature-Key", "header", rawData)
|
||||||
|
}
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: true
|
||||||
|
|
||||||
|
if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.XBearerSignatureKey = raw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindContainerID binds and validates parameter ContainerID from path.
|
||||||
|
func (o *SearchObjectsParams) bindContainerID(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: true
|
||||||
|
// Parameter is provided by construction from the route
|
||||||
|
o.ContainerID = raw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindLimit binds and validates parameter Limit from query.
|
||||||
|
func (o *SearchObjectsParams) bindLimit(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: false
|
||||||
|
// AllowEmptyValue: false
|
||||||
|
|
||||||
|
if raw == "" { // empty values pass all other validations
|
||||||
|
// Default values have been previously initialized by NewSearchObjectsParams()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := swag.ConvertInt64(raw)
|
||||||
|
if err != nil {
|
||||||
|
return errors.InvalidType("limit", "query", "int64", raw)
|
||||||
|
}
|
||||||
|
o.Limit = &value
|
||||||
|
|
||||||
|
if err := o.validateLimit(formats); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateLimit carries on validations for parameter Limit
|
||||||
|
func (o *SearchObjectsParams) validateLimit(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.MinimumInt("limit", "query", *o.Limit, 1, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validate.MaximumInt("limit", "query", *o.Limit, 10000, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindOffset binds and validates parameter Offset from query.
|
||||||
|
func (o *SearchObjectsParams) bindOffset(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: false
|
||||||
|
// AllowEmptyValue: false
|
||||||
|
|
||||||
|
if raw == "" { // empty values pass all other validations
|
||||||
|
// Default values have been previously initialized by NewSearchObjectsParams()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := swag.ConvertInt64(raw)
|
||||||
|
if err != nil {
|
||||||
|
return errors.InvalidType("offset", "query", "int64", raw)
|
||||||
|
}
|
||||||
|
o.Offset = &value
|
||||||
|
|
||||||
|
if err := o.validateOffset(formats); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateOffset carries on validations for parameter Offset
|
||||||
|
func (o *SearchObjectsParams) validateOffset(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.MinimumInt("offset", "query", *o.Offset, 0, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindWalletConnect binds and validates parameter WalletConnect from query.
|
||||||
|
func (o *SearchObjectsParams) bindWalletConnect(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: false
|
||||||
|
// AllowEmptyValue: false
|
||||||
|
|
||||||
|
if raw == "" { // empty values pass all other validations
|
||||||
|
// Default values have been previously initialized by NewSearchObjectsParams()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := swag.ConvertBool(raw)
|
||||||
|
if err != nil {
|
||||||
|
return errors.InvalidType("walletConnect", "query", "bool", raw)
|
||||||
|
}
|
||||||
|
o.WalletConnect = &value
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
100
gen/restapi/operations/search_objects_responses.go
Normal file
100
gen/restapi/operations/search_objects_responses.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package operations
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SearchObjectsOKCode is the HTTP code returned for type SearchObjectsOK
|
||||||
|
const SearchObjectsOKCode int = 200
|
||||||
|
|
||||||
|
/*SearchObjectsOK List of objects
|
||||||
|
|
||||||
|
swagger:response searchObjectsOK
|
||||||
|
*/
|
||||||
|
type SearchObjectsOK struct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
In: Body
|
||||||
|
*/
|
||||||
|
Payload *models.ObjectList `json:"body,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSearchObjectsOK creates SearchObjectsOK with default headers values
|
||||||
|
func NewSearchObjectsOK() *SearchObjectsOK {
|
||||||
|
|
||||||
|
return &SearchObjectsOK{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPayload adds the payload to the search objects o k response
|
||||||
|
func (o *SearchObjectsOK) WithPayload(payload *models.ObjectList) *SearchObjectsOK {
|
||||||
|
o.Payload = payload
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayload sets the payload to the search objects o k response
|
||||||
|
func (o *SearchObjectsOK) SetPayload(payload *models.ObjectList) {
|
||||||
|
o.Payload = payload
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteResponse to the client
|
||||||
|
func (o *SearchObjectsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||||
|
|
||||||
|
rw.WriteHeader(200)
|
||||||
|
if o.Payload != nil {
|
||||||
|
payload := o.Payload
|
||||||
|
if err := producer.Produce(rw, payload); err != nil {
|
||||||
|
panic(err) // let the recovery middleware deal with this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchObjectsBadRequestCode is the HTTP code returned for type SearchObjectsBadRequest
|
||||||
|
const SearchObjectsBadRequestCode int = 400
|
||||||
|
|
||||||
|
/*SearchObjectsBadRequest Bad request
|
||||||
|
|
||||||
|
swagger:response searchObjectsBadRequest
|
||||||
|
*/
|
||||||
|
type SearchObjectsBadRequest struct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
In: Body
|
||||||
|
*/
|
||||||
|
Payload models.Error `json:"body,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSearchObjectsBadRequest creates SearchObjectsBadRequest with default headers values
|
||||||
|
func NewSearchObjectsBadRequest() *SearchObjectsBadRequest {
|
||||||
|
|
||||||
|
return &SearchObjectsBadRequest{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPayload adds the payload to the search objects bad request response
|
||||||
|
func (o *SearchObjectsBadRequest) WithPayload(payload models.Error) *SearchObjectsBadRequest {
|
||||||
|
o.Payload = payload
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayload sets the payload to the search objects bad request response
|
||||||
|
func (o *SearchObjectsBadRequest) SetPayload(payload models.Error) {
|
||||||
|
o.Payload = payload
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteResponse to the client
|
||||||
|
func (o *SearchObjectsBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||||
|
|
||||||
|
rw.WriteHeader(400)
|
||||||
|
payload := o.Payload
|
||||||
|
if err := producer.Produce(rw, payload); err != nil {
|
||||||
|
panic(err) // let the recovery middleware deal with this
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler {
|
||||||
api.PutObjectHandler = operations.PutObjectHandlerFunc(a.PutObjects)
|
api.PutObjectHandler = operations.PutObjectHandlerFunc(a.PutObjects)
|
||||||
api.GetObjectInfoHandler = operations.GetObjectInfoHandlerFunc(a.GetObjectInfo)
|
api.GetObjectInfoHandler = operations.GetObjectInfoHandlerFunc(a.GetObjectInfo)
|
||||||
api.DeleteObjectHandler = operations.DeleteObjectHandlerFunc(a.DeleteObject)
|
api.DeleteObjectHandler = operations.DeleteObjectHandlerFunc(a.DeleteObject)
|
||||||
|
api.SearchObjectsHandler = operations.SearchObjectsHandlerFunc(a.SearchObjects)
|
||||||
|
|
||||||
api.PutContainerHandler = operations.PutContainerHandlerFunc(a.PutContainers)
|
api.PutContainerHandler = operations.PutContainerHandlerFunc(a.PutContainers)
|
||||||
api.GetContainerHandler = operations.GetContainerHandlerFunc(a.GetContainer)
|
api.GetContainerHandler = operations.GetContainerHandlerFunc(a.GetContainer)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -67,7 +68,7 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr
|
||||||
return errorResponse.WithPayload(NewError(err))
|
return errorResponse.WithPayload(NewError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp operations.PutObjectOKBody
|
var resp models.Address
|
||||||
resp.ContainerID = params.Object.ContainerID
|
resp.ContainerID = params.Object.ContainerID
|
||||||
resp.ObjectID = NewString(objID.String())
|
resp.ObjectID = NewString(objID.String())
|
||||||
|
|
||||||
|
@ -144,6 +145,109 @@ func (a *API) DeleteObject(params operations.DeleteObjectParams, principal *mode
|
||||||
return operations.NewDeleteObjectNoContent()
|
return operations.NewDeleteObjectNoContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchObjects handler that removes object from NeoFS.
|
||||||
|
func (a *API) SearchObjects(params operations.SearchObjectsParams, principal *models.Principal) middleware.Responder {
|
||||||
|
errorResponse := operations.NewSearchObjectsBadRequest()
|
||||||
|
ctx := params.HTTPRequest.Context()
|
||||||
|
|
||||||
|
var cnrID cid.ID
|
||||||
|
if err := cnrID.Parse(params.ContainerID); err != nil {
|
||||||
|
a.log.Error("invalid container id", zap.Error(err))
|
||||||
|
return errorResponse.WithPayload("invalid container id")
|
||||||
|
}
|
||||||
|
|
||||||
|
btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to get bearer token", zap.Error(err))
|
||||||
|
return errorResponse.WithPayload(NewError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
filters, err := ToNativeFilters(params.SearchFilters)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to transform to native", zap.Error(err))
|
||||||
|
return errorResponse.WithPayload(NewError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
var prm pool.PrmObjectSearch
|
||||||
|
prm.SetContainerID(cnrID)
|
||||||
|
prm.UseBearer(btoken)
|
||||||
|
prm.SetFilters(filters)
|
||||||
|
|
||||||
|
resSearch, err := a.pool.SearchObjects(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to search objects", zap.Error(err))
|
||||||
|
return errorResponse.WithPayload(NewError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := int(*params.Offset)
|
||||||
|
size := int(*params.Limit)
|
||||||
|
|
||||||
|
var iterateErr error
|
||||||
|
var obj *models.ObjectBaseInfo
|
||||||
|
var objects []*models.ObjectBaseInfo
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
err = resSearch.Iterate(func(id oid.ID) bool {
|
||||||
|
if i < offset {
|
||||||
|
i++
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj, iterateErr = headObjectBaseInfo(ctx, a.pool, &cnrID, &id, btoken); iterateErr != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
objects = append(objects, obj)
|
||||||
|
|
||||||
|
return len(objects) == size
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
err = iterateErr
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to search objects", zap.Error(err))
|
||||||
|
return errorResponse.WithPayload(NewError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
list := &models.ObjectList{
|
||||||
|
Size: NewInteger(int64(len(objects))),
|
||||||
|
Objects: objects,
|
||||||
|
}
|
||||||
|
|
||||||
|
return operations.NewSearchObjectsOK().WithPayload(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func headObjectBaseInfo(ctx context.Context, p *pool.Pool, cnrID *cid.ID, objID *oid.ID, btoken *token.BearerToken) (*models.ObjectBaseInfo, error) {
|
||||||
|
addr := address.NewAddress()
|
||||||
|
addr.SetContainerID(cnrID)
|
||||||
|
addr.SetObjectID(objID)
|
||||||
|
|
||||||
|
var prm pool.PrmObjectHead
|
||||||
|
prm.SetAddress(*addr)
|
||||||
|
prm.UseBearer(btoken)
|
||||||
|
|
||||||
|
objInfo, err := p.HeadObject(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &models.ObjectBaseInfo{
|
||||||
|
Address: &models.Address{
|
||||||
|
ContainerID: NewString(cnrID.String()),
|
||||||
|
ObjectID: NewString(objID.String()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attr := range objInfo.Attributes() {
|
||||||
|
if attr.Key() == object.AttributeFileName {
|
||||||
|
resp.Name = attr.Value()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseAddress(containerID, objectID string) (*address.Address, error) {
|
func parseAddress(containerID, objectID string) (*address.Address, error) {
|
||||||
var cnrID cid.ID
|
var cnrID cid.ID
|
||||||
if err := cnrID.Parse(containerID); err != nil {
|
if err := cnrID.Parse(containerID); err != nil {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
|
|
||||||
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
@ -391,3 +392,40 @@ func ToNativeTable(records []*models.Record) (*eacl.Table, error) {
|
||||||
|
|
||||||
return table, nil
|
return table, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToNativeMatchFilter converts models.SearchMatch to object.SearchMatchType.
|
||||||
|
func ToNativeMatchFilter(s *models.SearchMatch) (object.SearchMatchType, error) {
|
||||||
|
if s == nil {
|
||||||
|
return object.MatchUnknown, fmt.Errorf("unsupported empty verb type")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *s {
|
||||||
|
case models.SearchMatchMatchStringEqual:
|
||||||
|
return object.MatchStringEqual, nil
|
||||||
|
case models.SearchMatchMatchStringNotEqual:
|
||||||
|
return object.MatchStringNotEqual, nil
|
||||||
|
case models.SearchMatchMatchNotPresent:
|
||||||
|
return object.MatchNotPresent, nil
|
||||||
|
case models.SearchMatchMatchCommonPrefix:
|
||||||
|
return object.MatchCommonPrefix, nil
|
||||||
|
default:
|
||||||
|
return object.MatchUnknown, fmt.Errorf("unsupported search match: '%s'", *s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToNativeFilters converts models.SearchFilters to object.SearchFilters.
|
||||||
|
func ToNativeFilters(fs *models.SearchFilters) (object.SearchFilters, error) {
|
||||||
|
filters := object.NewSearchFilters()
|
||||||
|
filters.AddRootFilter()
|
||||||
|
|
||||||
|
for _, f := range fs.Filters {
|
||||||
|
matchFilter, err := ToNativeMatchFilter(f.Match)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filters.AddFilter(*f.Key, *f.Value, matchFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters, nil
|
||||||
|
}
|
||||||
|
|
115
spec/rest.yaml
115
spec/rest.yaml
|
@ -130,18 +130,46 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: Address of uploaded objects
|
description: Address of uploaded objects
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: '#/definitions/Address'
|
||||||
properties:
|
400:
|
||||||
objectId:
|
description: Bad request
|
||||||
type: string
|
schema:
|
||||||
containerId:
|
$ref: '#/definitions/Error'
|
||||||
type: string
|
|
||||||
required:
|
/objects/{containerId}/search:
|
||||||
- objectId
|
parameters:
|
||||||
- containerId
|
- $ref: '#/parameters/signatureParam'
|
||||||
example:
|
- $ref: '#/parameters/signatureKeyParam'
|
||||||
objectId: 8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd
|
- $ref: '#/parameters/signatureScheme'
|
||||||
containerId: 5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv
|
- $ref: '#/parameters/containerId'
|
||||||
|
post:
|
||||||
|
operationId: searchObjects
|
||||||
|
summary: Search objects by filters
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: offset
|
||||||
|
type: integer
|
||||||
|
default: 0
|
||||||
|
minimum: 0
|
||||||
|
description: The number of containers to skip before starting to collect the result set.
|
||||||
|
- in: query
|
||||||
|
name: limit
|
||||||
|
type: integer
|
||||||
|
default: 100
|
||||||
|
minimum: 1
|
||||||
|
maximum: 10000
|
||||||
|
description: The numbers of containers to return.
|
||||||
|
- in: body
|
||||||
|
required: true
|
||||||
|
name: searchFilters
|
||||||
|
description: Filters to search objects
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/SearchFilters'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: List of objects
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ObjectList'
|
||||||
400:
|
400:
|
||||||
description: Bad request
|
description: Bad request
|
||||||
schema:
|
schema:
|
||||||
|
@ -513,6 +541,35 @@ definitions:
|
||||||
required:
|
required:
|
||||||
- size
|
- size
|
||||||
- containers
|
- containers
|
||||||
|
SearchFilters:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
filters:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/SearchFilter'
|
||||||
|
required:
|
||||||
|
- filters
|
||||||
|
SearchFilter:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
|
match:
|
||||||
|
$ref: '#/definitions/SearchMatch'
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- value
|
||||||
|
- match
|
||||||
|
SearchMatch:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- MatchStringEqual
|
||||||
|
- MatchStringNotEqual
|
||||||
|
- MatchNotPresent
|
||||||
|
- MatchCommonPrefix
|
||||||
ContainerBaseInfo:
|
ContainerBaseInfo:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -522,6 +579,27 @@ definitions:
|
||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
- containerId
|
- containerId
|
||||||
|
ObjectList:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
type: integer
|
||||||
|
objects:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/ObjectBaseInfo'
|
||||||
|
required:
|
||||||
|
- size
|
||||||
|
- objects
|
||||||
|
ObjectBaseInfo:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
address:
|
||||||
|
$ref: '#/definitions/Address'
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- address
|
||||||
ObjectInfo:
|
ObjectInfo:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -549,6 +627,19 @@ definitions:
|
||||||
value: "1648810072"
|
value: "1648810072"
|
||||||
- key: Name
|
- key: Name
|
||||||
value: object
|
value: object
|
||||||
|
Address:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
containerId:
|
||||||
|
type: string
|
||||||
|
objectId:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- containerId
|
||||||
|
- objectId
|
||||||
|
example:
|
||||||
|
objectId: 8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd
|
||||||
|
containerId: 5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv
|
||||||
Eacl:
|
Eacl:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
Reference in a new issue