[#1] Add route to get object info

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2022-04-11 14:18:26 +03:00 committed by Alex Vanin
parent d9798cbce8
commit 066656ac48
14 changed files with 1032 additions and 70 deletions

View file

@ -8,8 +8,10 @@ package models
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// Attribute attribute
@ -18,14 +20,47 @@ import (
type Attribute struct {
// key
Key string `json:"key,omitempty"`
// Required: true
Key *string `json:"key"`
// value
Value string `json:"value,omitempty"`
// Required: true
Value *string `json:"value"`
}
// Validate validates this attribute
func (m *Attribute) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateKey(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 *Attribute) validateKey(formats strfmt.Registry) error {
if err := validate.Required("key", "body", m.Key); err != nil {
return err
}
return nil
}
func (m *Attribute) validateValue(formats strfmt.Registry) error {
if err := validate.Required("value", "body", m.Value); err != nil {
return err
}
return nil
}

View file

@ -12,6 +12,7 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// ContainerInfo container info
@ -21,22 +22,28 @@ import (
type ContainerInfo struct {
// attributes
// Required: true
Attributes []*Attribute `json:"attributes"`
// basic Acl
BasicACL string `json:"basicAcl,omitempty"`
// Required: true
BasicACL *string `json:"basicAcl"`
// container Id
ContainerID string `json:"containerId,omitempty"`
// Required: true
ContainerID *string `json:"containerId"`
// owner Id
OwnerID string `json:"ownerId,omitempty"`
// Required: true
OwnerID *string `json:"ownerId"`
// placement policy
PlacementPolicy string `json:"placementPolicy,omitempty"`
// Required: true
PlacementPolicy *string `json:"placementPolicy"`
// version
Version string `json:"version,omitempty"`
// Required: true
Version *string `json:"version"`
}
// Validate validates this container info
@ -47,6 +54,26 @@ func (m *ContainerInfo) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateBasicACL(formats); err != nil {
res = append(res, err)
}
if err := m.validateContainerID(formats); err != nil {
res = append(res, err)
}
if err := m.validateOwnerID(formats); err != nil {
res = append(res, err)
}
if err := m.validatePlacementPolicy(formats); err != nil {
res = append(res, err)
}
if err := m.validateVersion(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
@ -54,8 +81,9 @@ func (m *ContainerInfo) Validate(formats strfmt.Registry) error {
}
func (m *ContainerInfo) validateAttributes(formats strfmt.Registry) error {
if swag.IsZero(m.Attributes) { // not required
return nil
if err := validate.Required("attributes", "body", m.Attributes); err != nil {
return err
}
for i := 0; i < len(m.Attributes); i++ {
@ -79,6 +107,51 @@ func (m *ContainerInfo) validateAttributes(formats strfmt.Registry) error {
return nil
}
func (m *ContainerInfo) validateBasicACL(formats strfmt.Registry) error {
if err := validate.Required("basicAcl", "body", m.BasicACL); err != nil {
return err
}
return nil
}
func (m *ContainerInfo) validateContainerID(formats strfmt.Registry) error {
if err := validate.Required("containerId", "body", m.ContainerID); err != nil {
return err
}
return nil
}
func (m *ContainerInfo) validateOwnerID(formats strfmt.Registry) error {
if err := validate.Required("ownerId", "body", m.OwnerID); err != nil {
return err
}
return nil
}
func (m *ContainerInfo) validatePlacementPolicy(formats strfmt.Registry) error {
if err := validate.Required("placementPolicy", "body", m.PlacementPolicy); err != nil {
return err
}
return nil
}
func (m *ContainerInfo) validateVersion(formats strfmt.Registry) error {
if err := validate.Required("version", "body", m.Version); err != nil {
return err
}
return nil
}
// ContextValidate validate this container info based on the context it is used
func (m *ContainerInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error

171
gen/models/object_info.go Normal file
View file

@ -0,0 +1,171 @@
// 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"
)
// ObjectInfo object info
// Example: {"attribute":[{"key":"Timestamp","value":"1648810072"},{"key":"Name","value":"object"}],"containerId":"5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv","objectId":"8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd","ownerId":"NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"}
//
// swagger:model ObjectInfo
type ObjectInfo struct {
// attributes
// Required: true
Attributes []*Attribute `json:"attributes"`
// container Id
// Required: true
ContainerID *string `json:"containerId"`
// object Id
// Required: true
ObjectID *string `json:"objectId"`
// owner Id
// Required: true
OwnerID *string `json:"ownerId"`
}
// Validate validates this object info
func (m *ObjectInfo) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateAttributes(formats); err != nil {
res = append(res, err)
}
if err := m.validateContainerID(formats); err != nil {
res = append(res, err)
}
if err := m.validateObjectID(formats); err != nil {
res = append(res, err)
}
if err := m.validateOwnerID(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ObjectInfo) validateAttributes(formats strfmt.Registry) error {
if err := validate.Required("attributes", "body", m.Attributes); err != nil {
return err
}
for i := 0; i < len(m.Attributes); i++ {
if swag.IsZero(m.Attributes[i]) { // not required
continue
}
if m.Attributes[i] != nil {
if err := m.Attributes[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("attributes" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("attributes" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *ObjectInfo) validateContainerID(formats strfmt.Registry) error {
if err := validate.Required("containerId", "body", m.ContainerID); err != nil {
return err
}
return nil
}
func (m *ObjectInfo) validateObjectID(formats strfmt.Registry) error {
if err := validate.Required("objectId", "body", m.ObjectID); err != nil {
return err
}
return nil
}
func (m *ObjectInfo) validateOwnerID(formats strfmt.Registry) error {
if err := validate.Required("ownerId", "body", m.OwnerID); err != nil {
return err
}
return nil
}
// ContextValidate validate this object info based on the context it is used
func (m *ObjectInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateAttributes(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ObjectInfo) contextValidateAttributes(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Attributes); i++ {
if m.Attributes[i] != nil {
if err := m.Attributes[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("attributes" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("attributes" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *ObjectInfo) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ObjectInfo) UnmarshalBinary(b []byte) error {
var res ObjectInfo
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View file

@ -155,18 +155,10 @@ func init() {
},
"parameters": [
{
"type": "string",
"description": "Base64 encoded signature for bearer token",
"name": "X-Neofs-Token-Signature",
"in": "header",
"required": true
"$ref": "#/parameters/signatureParam"
},
{
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-signature-Key",
"in": "header",
"required": true
"$ref": "#/parameters/signatureKeyParam"
}
]
},
@ -273,18 +265,52 @@ func init() {
}
},
"parameters": [
{
"$ref": "#/parameters/signatureParam"
},
{
"$ref": "#/parameters/signatureKeyParam"
}
]
},
"/objects/{containerId}/{objectId}": {
"get": {
"summary": "Get object info by address and",
"operationId": "getObjectInfo",
"responses": {
"200": {
"description": "Object info",
"schema": {
"$ref": "#/definitions/ObjectInfo"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"parameters": [
{
"$ref": "#/parameters/signatureParam"
},
{
"$ref": "#/parameters/signatureKeyParam"
},
{
"type": "string",
"description": "Base64 encoded signature for bearer token",
"name": "X-Neofs-Token-Signature",
"in": "header",
"description": "Base58 encoded container id",
"name": "containerId",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-Signature-Key",
"in": "header",
"description": "Base58 encoded object id",
"name": "objectId",
"in": "path",
"required": true
}
]
@ -300,6 +326,10 @@ func init() {
},
"Attribute": {
"type": "object",
"required": [
"key",
"value"
],
"properties": {
"key": {
"type": "string"
@ -325,6 +355,14 @@ func init() {
},
"ContainerInfo": {
"type": "object",
"required": [
"containerId",
"version",
"ownerId",
"basicAcl",
"placementPolicy",
"attributes"
],
"properties": {
"attributes": {
"type": "array",
@ -413,6 +451,47 @@ func init() {
"STRING_NOT_EQUAL"
]
},
"ObjectInfo": {
"type": "object",
"required": [
"containerId",
"objectId",
"ownerId",
"attributes"
],
"properties": {
"attributes": {
"type": "array",
"items": {
"$ref": "#/definitions/Attribute"
}
},
"containerId": {
"type": "string"
},
"objectId": {
"type": "string"
},
"ownerId": {
"type": "string"
}
},
"example": {
"attribute": [
{
"key": "Timestamp",
"value": "1648810072"
},
{
"key": "Name",
"value": "object"
}
],
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd",
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
}
},
"Operation": {
"type": "string",
"enum": [
@ -555,8 +634,25 @@ func init() {
]
}
},
"parameters": {
"signatureKeyParam": {
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-Signature-Key",
"in": "header",
"required": true
},
"signatureParam": {
"type": "string",
"description": "Base64 encoded signature for bearer token",
"name": "X-Neofs-Token-Signature",
"in": "header",
"required": true
}
},
"securityDefinitions": {
"BearerAuth": {
"description": "Bearer token body to provide with NeoFS request. Must have 'Bearer ' prefix.",
"type": "apiKey",
"name": "Authorization",
"in": "header"
@ -715,7 +811,7 @@ func init() {
{
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-signature-Key",
"name": "X-Neofs-Token-Signature-Key",
"in": "header",
"required": true
}
@ -839,6 +935,56 @@ func init() {
"required": true
}
]
},
"/objects/{containerId}/{objectId}": {
"get": {
"summary": "Get object info by address and",
"operationId": "getObjectInfo",
"responses": {
"200": {
"description": "Object info",
"schema": {
"$ref": "#/definitions/ObjectInfo"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"parameters": [
{
"type": "string",
"description": "Base64 encoded signature for bearer token",
"name": "X-Neofs-Token-Signature",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-Signature-Key",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Base58 encoded container id",
"name": "containerId",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Base58 encoded object id",
"name": "objectId",
"in": "path",
"required": true
}
]
}
},
"definitions": {
@ -851,6 +997,10 @@ func init() {
},
"Attribute": {
"type": "object",
"required": [
"key",
"value"
],
"properties": {
"key": {
"type": "string"
@ -876,6 +1026,14 @@ func init() {
},
"ContainerInfo": {
"type": "object",
"required": [
"containerId",
"version",
"ownerId",
"basicAcl",
"placementPolicy",
"attributes"
],
"properties": {
"attributes": {
"type": "array",
@ -964,6 +1122,47 @@ func init() {
"STRING_NOT_EQUAL"
]
},
"ObjectInfo": {
"type": "object",
"required": [
"containerId",
"objectId",
"ownerId",
"attributes"
],
"properties": {
"attributes": {
"type": "array",
"items": {
"$ref": "#/definitions/Attribute"
}
},
"containerId": {
"type": "string"
},
"objectId": {
"type": "string"
},
"ownerId": {
"type": "string"
}
},
"example": {
"attribute": [
{
"key": "Timestamp",
"value": "1648810072"
},
{
"key": "Name",
"value": "object"
}
],
"containerId": "5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv",
"objectId": "8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd",
"ownerId": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM"
}
},
"Operation": {
"type": "string",
"enum": [
@ -1106,8 +1305,25 @@ func init() {
]
}
},
"parameters": {
"signatureKeyParam": {
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token",
"name": "X-Neofs-Token-Signature-Key",
"in": "header",
"required": true
},
"signatureParam": {
"type": "string",
"description": "Base64 encoded signature for bearer token",
"name": "X-Neofs-Token-Signature",
"in": "header",
"required": true
}
},
"securityDefinitions": {
"BearerAuth": {
"description": "Bearer token body to provide with NeoFS request. Must have 'Bearer ' prefix.",
"type": "apiKey",
"name": "Authorization",
"in": "header"

View 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"
)
// GetObjectInfoHandlerFunc turns a function with the right signature into a get object info handler
type GetObjectInfoHandlerFunc func(GetObjectInfoParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn GetObjectInfoHandlerFunc) Handle(params GetObjectInfoParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// GetObjectInfoHandler interface for that can handle valid get object info params
type GetObjectInfoHandler interface {
Handle(GetObjectInfoParams, *models.Principal) middleware.Responder
}
// NewGetObjectInfo creates a new http.Handler for the get object info operation
func NewGetObjectInfo(ctx *middleware.Context, handler GetObjectInfoHandler) *GetObjectInfo {
return &GetObjectInfo{Context: ctx, Handler: handler}
}
/* GetObjectInfo swagger:route GET /objects/{containerId}/{objectId} getObjectInfo
Get object info by address and
*/
type GetObjectInfo struct {
Context *middleware.Context
Handler GetObjectInfoHandler
}
func (o *GetObjectInfo) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewGetObjectInfoParams()
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)
}

View file

@ -0,0 +1,154 @@
// 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/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
)
// NewGetObjectInfoParams creates a new GetObjectInfoParams object
//
// There are no default values defined in the spec.
func NewGetObjectInfoParams() GetObjectInfoParams {
return GetObjectInfoParams{}
}
// GetObjectInfoParams contains all the bound params for the get object info operation
// typically these are obtained from a http.Request
//
// swagger:parameters getObjectInfo
type GetObjectInfoParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*Base64 encoded signature for bearer token
Required: true
In: header
*/
XNeofsTokenSignature string
/*Hex encoded the public part of the key that signed the bearer token
Required: true
In: header
*/
XNeofsTokenSignatureKey string
/*Base58 encoded container id
Required: true
In: path
*/
ContainerID string
/*Base58 encoded object id
Required: true
In: path
*/
ObjectID string
}
// 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 NewGetObjectInfoParams() beforehand.
func (o *GetObjectInfoParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil {
res = append(res, err)
}
if err := o.bindXNeofsTokenSignatureKey(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-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)
}
rObjectID, rhkObjectID, _ := route.Params.GetOK("objectId")
if err := o.bindObjectID(rObjectID, rhkObjectID, route.Formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header.
func (o *GetObjectInfoParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error {
if !hasKey {
return errors.Required("X-Neofs-Token-Signature", "header", rawData)
}
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil {
return err
}
o.XNeofsTokenSignature = raw
return nil
}
// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header.
func (o *GetObjectInfoParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error {
if !hasKey {
return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData)
}
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil {
return err
}
o.XNeofsTokenSignatureKey = raw
return nil
}
// bindContainerID binds and validates parameter ContainerID from path.
func (o *GetObjectInfoParams) 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
}
// bindObjectID binds and validates parameter ObjectID from path.
func (o *GetObjectInfoParams) bindObjectID(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.ObjectID = raw
return nil
}

View 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"
)
// GetObjectInfoOKCode is the HTTP code returned for type GetObjectInfoOK
const GetObjectInfoOKCode int = 200
/*GetObjectInfoOK Object info
swagger:response getObjectInfoOK
*/
type GetObjectInfoOK struct {
/*
In: Body
*/
Payload *models.ObjectInfo `json:"body,omitempty"`
}
// NewGetObjectInfoOK creates GetObjectInfoOK with default headers values
func NewGetObjectInfoOK() *GetObjectInfoOK {
return &GetObjectInfoOK{}
}
// WithPayload adds the payload to the get object info o k response
func (o *GetObjectInfoOK) WithPayload(payload *models.ObjectInfo) *GetObjectInfoOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the get object info o k response
func (o *GetObjectInfoOK) SetPayload(payload *models.ObjectInfo) {
o.Payload = payload
}
// WriteResponse to the client
func (o *GetObjectInfoOK) 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
}
}
}
// GetObjectInfoBadRequestCode is the HTTP code returned for type GetObjectInfoBadRequest
const GetObjectInfoBadRequestCode int = 400
/*GetObjectInfoBadRequest Bad request
swagger:response getObjectInfoBadRequest
*/
type GetObjectInfoBadRequest struct {
/*
In: Body
*/
Payload models.Error `json:"body,omitempty"`
}
// NewGetObjectInfoBadRequest creates GetObjectInfoBadRequest with default headers values
func NewGetObjectInfoBadRequest() *GetObjectInfoBadRequest {
return &GetObjectInfoBadRequest{}
}
// WithPayload adds the payload to the get object info bad request response
func (o *GetObjectInfoBadRequest) WithPayload(payload models.Error) *GetObjectInfoBadRequest {
o.Payload = payload
return o
}
// SetPayload sets the payload to the get object info bad request response
func (o *GetObjectInfoBadRequest) SetPayload(payload models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *GetObjectInfoBadRequest) 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
}
}

View file

@ -50,6 +50,9 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI {
GetContainerHandler: GetContainerHandlerFunc(func(params GetContainerParams) middleware.Responder {
return middleware.NotImplemented("operation GetContainer has not yet been implemented")
}),
GetObjectInfoHandler: GetObjectInfoHandlerFunc(func(params GetObjectInfoParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation GetObjectInfo has not yet been implemented")
}),
PutContainerHandler: PutContainerHandlerFunc(func(params PutContainerParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation PutContainer has not yet been implemented")
}),
@ -110,6 +113,8 @@ type NeofsRestGwAPI struct {
AuthHandler AuthHandler
// GetContainerHandler sets the operation handler for the get container operation
GetContainerHandler GetContainerHandler
// GetObjectInfoHandler sets the operation handler for the get object info operation
GetObjectInfoHandler GetObjectInfoHandler
// PutContainerHandler sets the operation handler for the put container operation
PutContainerHandler PutContainerHandler
// PutObjectHandler sets the operation handler for the put object operation
@ -201,6 +206,9 @@ func (o *NeofsRestGwAPI) Validate() error {
if o.GetContainerHandler == nil {
unregistered = append(unregistered, "GetContainerHandler")
}
if o.GetObjectInfoHandler == nil {
unregistered = append(unregistered, "GetObjectInfoHandler")
}
if o.PutContainerHandler == nil {
unregistered = append(unregistered, "PutContainerHandler")
}
@ -314,6 +322,10 @@ func (o *NeofsRestGwAPI) initHandlerCache() {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/containers/{containerId}"] = NewGetContainer(o.context, o.GetContainerHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/objects/{containerId}/{objectId}"] = NewGetObjectInfo(o.context, o.GetObjectInfoHandler)
if o.handlers["PUT"] == nil {
o.handlers["PUT"] = make(map[string]http.Handler)
}

View file

@ -64,7 +64,7 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc
res = append(res, err)
}
if err := o.bindXNeofsTokenSignatureKey(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-signature-Key")], true, route.Formats); err != nil {
if err := o.bindXNeofsTokenSignatureKey(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature-Key")], true, route.Formats); err != nil {
res = append(res, err)
}
@ -124,7 +124,7 @@ func (o *PutContainerParams) bindXNeofsTokenSignature(rawData []string, hasKey b
// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header.
func (o *PutContainerParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error {
if !hasKey {
return errors.Required("X-Neofs-Token-signature-Key", "header", rawData)
return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData)
}
var raw string
if len(rawData) > 0 {
@ -133,7 +133,7 @@ func (o *PutContainerParams) bindXNeofsTokenSignatureKey(rawData []string, hasKe
// Required: true
if err := validate.RequiredString("X-Neofs-Token-signature-Key", "header", raw); err != nil {
if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil {
return err
}
o.XNeofsTokenSignatureKey = raw

View file

@ -41,10 +41,10 @@ type BearerToken struct {
type ContextKey string
const (
// BearerPrefix is the prefix for authorization token
// BearerPrefix is the prefix for authorization token.
BearerPrefix = "Bearer "
// ContextKeyRequestID is the ContextKey for RequestID
// ContextKeyRequestID is the ContextKey for RequestID.
ContextKeyRequestID ContextKey = "requestID"
)
@ -62,9 +62,13 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler {
api.ServeError = errors.ServeError
api.AuthHandler = operations.AuthHandlerFunc(a.PostAuth)
api.PutObjectHandler = operations.PutObjectHandlerFunc(a.PutObjects)
api.GetObjectInfoHandler = operations.GetObjectInfoHandlerFunc(a.GetObjectInfo)
api.PutContainerHandler = operations.PutContainerHandlerFunc(a.PutContainers)
api.GetContainerHandler = operations.GetContainerHandlerFunc(a.GetContainer)
api.BearerAuthAuth = func(s string) (*models.Principal, error) {
if !strings.HasPrefix(s, BearerPrefix) {
return nil, fmt.Errorf("has not bearer token")

View file

@ -62,15 +62,18 @@ func (a *API) GetContainer(params operations.GetContainerParams) middleware.Resp
attrs := make([]*models.Attribute, len(cnr.Attributes()))
for i, attr := range cnr.Attributes() {
attrs[i] = &models.Attribute{Key: attr.Key(), Value: attr.Value()}
attrs[i] = &models.Attribute{
Key: NewString(attr.Key()),
Value: NewString(attr.Value()),
}
}
resp := &models.ContainerInfo{
ContainerID: params.ContainerID,
Version: cnr.Version().String(),
OwnerID: cnr.OwnerID().String(),
BasicACL: acl.BasicACL(cnr.BasicACL()).String(),
PlacementPolicy: strings.Join(policy.Encode(cnr.PlacementPolicy()), " "),
ContainerID: NewString(params.ContainerID),
Version: NewString(cnr.Version().String()),
OwnerID: NewString(cnr.OwnerID().String()),
BasicACL: NewString(acl.BasicACL(cnr.BasicACL()).String()),
PlacementPolicy: NewString(strings.Join(policy.Encode(cnr.PlacementPolicy()), " ")),
Attributes: attrs,
}

View file

@ -4,6 +4,10 @@ import (
"encoding/base64"
"fmt"
"github.com/nspcc-dev/neofs-sdk-go/object/address"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"go.uber.org/zap"
"github.com/go-openapi/runtime/middleware"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-api-go/v2/acl"
@ -18,6 +22,7 @@ import (
// PutObjects handler that uploads object to NeoFS.
func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Principal) middleware.Responder {
errorResponse := operations.NewPutObjectBadRequest()
ctx := params.HTTPRequest.Context()
bt := &BearerToken{
@ -28,17 +33,18 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr
btoken, err := prepareBearerToken(bt)
if err != nil {
return operations.NewPutObjectBadRequest().WithPayload(models.Error(err.Error()))
return errorResponse.WithPayload(models.Error(err.Error()))
}
var cnrID cid.ID
if err = cnrID.Parse(*params.Object.ContainerID); err != nil {
return operations.NewPutObjectBadRequest().WithPayload(models.Error(err.Error()))
a.log.Error("invalid container id", zap.Error(err))
return errorResponse.WithPayload("invalid container id")
}
payload, err := base64.StdEncoding.DecodeString(params.Object.Payload)
if err != nil {
return operations.NewPutObjectBadRequest().WithPayload(models.Error(err.Error()))
return errorResponse.WithPayload(models.Error(err.Error()))
}
prm := PrmAttributes{
@ -47,7 +53,7 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr
}
attributes, err := GetObjectAttributes(ctx, params.HTTPRequest.Header, a.pool, prm)
if err != nil {
return operations.NewPutObjectBadRequest().WithPayload(models.Error(err.Error()))
return errorResponse.WithPayload(models.Error(err.Error()))
}
obj := object.New()
@ -62,7 +68,7 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr
objID, err := a.pool.PutObject(ctx, prmPut)
if err != nil {
return operations.NewPutObjectBadRequest().WithPayload(models.Error(err.Error()))
return errorResponse.WithPayload(NewError(err))
}
var resp operations.PutObjectOKBody
@ -72,6 +78,61 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr
return operations.NewPutObjectOK().WithPayload(&resp)
}
// GetObjectInfo handler that get object info.
func (a *API) GetObjectInfo(params operations.GetObjectInfoParams, principal *models.Principal) middleware.Responder {
errorResponse := operations.NewGetObjectInfoBadRequest()
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")
}
var objID oid.ID
if err := objID.Parse(params.ObjectID); err != nil {
a.log.Error("invalid object id", zap.Error(err))
return errorResponse.WithPayload("invalid object id")
}
bt := &BearerToken{
Token: string(*principal),
Signature: params.XNeofsTokenSignature,
Key: params.XNeofsTokenSignatureKey,
}
btoken, err := prepareBearerToken(bt)
if err != nil {
return errorResponse.WithPayload(NewError(err))
}
var prm pool.PrmObjectHead
addr := address.NewAddress()
addr.SetContainerID(&cnrID)
addr.SetObjectID(&objID)
prm.SetAddress(*addr)
prm.UseBearer(btoken)
objInfo, err := a.pool.HeadObject(ctx, prm)
if err != nil {
return errorResponse.WithPayload(NewError(err))
}
var resp models.ObjectInfo
resp.ContainerID = NewString(params.ContainerID)
resp.ObjectID = NewString(params.ObjectID)
resp.OwnerID = NewString(objInfo.OwnerID().String())
resp.Attributes = make([]*models.Attribute, len(objInfo.Attributes()))
for i, attr := range objInfo.Attributes() {
resp.Attributes[i] = &models.Attribute{
Key: NewString(attr.Key()),
Value: NewString(attr.Value()),
}
}
return operations.NewGetObjectInfoOK().WithPayload(&resp)
}
func prepareBearerToken(bt *BearerToken) (*token.BearerToken, error) {
btoken, err := getBearerToken(bt.Token)
if err != nil {

View file

@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
objectv2 "github.com/nspcc-dev/neofs-api-go/v2/object"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/object"
@ -216,3 +218,7 @@ func updateExpirationHeader(headers map[string]string, durations *epochDurations
func NewString(val string) *string {
return &val
}
func NewError(err error) models.Error {
return models.Error(err.Error())
}

View file

@ -15,10 +15,25 @@ securityDefinitions:
type: apiKey
in: header
name: Authorization
description: Bearer token body to provide with NeoFS request. Must have 'Bearer ' prefix.
security:
- BearerAuth: [ ]
parameters:
signatureParam:
in: header
name: X-Neofs-Token-Signature
description: Base64 encoded signature for bearer token
type: string
required: true
signatureKeyParam:
in: header
name: X-Neofs-Token-Signature-Key
description: Hex encoded the public part of the key that signed the bearer token
type: string
required: true
paths:
/auth:
post:
@ -66,20 +81,8 @@ paths:
/objects:
parameters:
- in: header
name: X-Neofs-Token-Signature
description: Base64 encoded signature for bearer token
type: string
required: true
# example:
# BGtqMEpzxTabrdIIIDAnL79Cs7bm46+8lsFaMMU+LCKw/ujEjF0r5mVLKixWmxoreuj1E0BXWcqp9d3wGV6Hc9I=
- in: header
name: X-Neofs-Token-Signature-Key
description: Hex encoded the public part of the key that signed the bearer token
type: string
required: true
# example:
# 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a
- $ref: '#/parameters/signatureParam'
- $ref: '#/parameters/signatureKeyParam'
put:
operationId: putObject
summary: Upload object to NeoFS
@ -129,22 +132,37 @@ paths:
schema:
$ref: '#/definitions/Error'
/objects/{containerId}/{objectId}:
parameters:
- $ref: '#/parameters/signatureParam'
- $ref: '#/parameters/signatureKeyParam'
- in: path
name: containerId
type: string
required: true
description: Base58 encoded container id
- in: path
name: objectId
type: string
required: true
description: Base58 encoded object id
get:
operationId: getObjectInfo
summary: Get object info by address and
responses:
200:
description: Object info
schema:
$ref: '#/definitions/ObjectInfo'
400:
description: Bad request
schema:
$ref: '#/definitions/Error'
/containers:
parameters:
- in: header
name: X-Neofs-Token-Signature
description: Base64 encoded signature for bearer token
type: string
required: true
# example:
# BEvF1N0heytTXn1p2ZV3jN8YM25YkG4FxHmPeq2kWP5HeHCAN4cDjONyX6Bh30Ypw6Kfch2nYOfhiL+rClYQJ9Q=
- in: header
name: X-Neofs-Token-signature-Key
description: Hex encoded the public part of the key that signed the bearer token
type: string
required: true
# example:
# 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a
- $ref: '#/parameters/signatureParam'
- $ref: '#/parameters/signatureKeyParam'
put:
operationId: putContainer
summary: Create new container in NeoFS
@ -364,6 +382,13 @@ definitions:
type: array
items:
$ref: '#/definitions/Attribute'
required:
- containerId
- version
- ownerId
- basicAcl
- placementPolicy
- attributes
example:
containerId: 5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv
version: "2.11"
@ -375,6 +400,34 @@ definitions:
value: "1648810072"
- key: Name
value: container
ObjectInfo:
type: object
properties:
containerId:
type: string
objectId:
type: string
ownerId:
type: string
attributes:
type: array
items:
$ref: '#/definitions/Attribute'
required:
- containerId
- objectId
- ownerId
- attributes
example:
containerId: 5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv
objectId: 8N3o7Dtr6T1xteCt6eRwhpmJ7JhME58Hyu1dvaswuTDd
ownerId: NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM
attribute:
- key: Timestamp
value: "1648810072"
- key: Name
value: object
Attribute:
type: object
properties:
@ -382,6 +435,9 @@ definitions:
type: string
value:
type: string
required:
- key
- value
Principal:
type: string
Error: