From f5eab95f9547b2cdd3984e5e71e0f23a0f66ce9b Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 14 Apr 2022 11:53:13 +0300 Subject: [PATCH] [#1] Add route to delete object Signed-off-by: Denis Kirillov --- cmd/neofs-rest-gw/integration_test.go | 71 ++++++-- gen/restapi/embedded_spec.go | 100 +++++++----- gen/restapi/operations/auth_parameters.go | 54 +++--- .../operations/delete_container_parameters.go | 28 ++-- gen/restapi/operations/delete_object.go | 71 ++++++++ .../operations/delete_object_parameters.go | 154 ++++++++++++++++++ .../operations/delete_object_responses.go | 80 +++++++++ .../operations/get_object_info_parameters.go | 28 ++-- gen/restapi/operations/neofs_rest_gw_api.go | 12 ++ .../put_container_e_acl_parameters.go | 28 ++-- .../operations/put_container_parameters.go | 28 ++-- .../operations/put_object_parameters.go | 28 ++-- handlers/api.go | 1 + handlers/auth.go | 8 +- handlers/containers.go | 14 +- handlers/objects.go | 99 +++++++---- spec/rest.yaml | 32 ++-- 17 files changed, 624 insertions(+), 212 deletions(-) create mode 100644 gen/restapi/operations/delete_object.go create mode 100644 gen/restapi/operations/delete_object_parameters.go create mode 100644 gen/restapi/operations/delete_object_responses.go diff --git a/cmd/neofs-rest-gw/integration_test.go b/cmd/neofs-rest-gw/integration_test.go index a4352ba..9cfd740 100644 --- a/cmd/neofs-rest-gw/integration_test.go +++ b/cmd/neofs-rest-gw/integration_test.go @@ -45,13 +45,13 @@ const ( testNode = "localhost:8080" containerName = "test-container" - // XNeofsTokenSignature header contains base64 encoded signature of the token body. - XNeofsTokenSignature = "X-Neofs-Token-Signature" - // XNeofsTokenSignatureKey header contains hex encoded public key that corresponds the signature of the token body. - XNeofsTokenSignatureKey = "X-Neofs-Token-Signature-Key" - // XNeofsTokenScope header contains operation scope for auth (bearer) token. + // XBearerSignature header contains base64 encoded signature of the token body. + XBearerSignature = "X-Bearer-Signature" + // XBearerSignatureKey header contains hex encoded public key that corresponds the signature of the token body. + XBearerSignatureKey = "X-Bearer-Signature-Key" + // XBearerScope header contains operation scope for auth (bearer) token. // It corresponds to 'object' or 'container' services in neofs. - XNeofsTokenScope = "X-Neofs-Token-Scope" + XBearerScope = "X-Bearer-Scope" ) func TestIntegration(t *testing.T) { @@ -74,15 +74,17 @@ func TestIntegration(t *testing.T) { cancel := runServer(ctx, t) clientPool := getPool(ctx, t, key) cnrID := createContainer(ctx, t, clientPool, containerName) + restrictByEACL(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 delete object "+version, func(t *testing.T) { restObjectDelete(ctx, t, clientPool, cnrID) }) 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 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 get container eacl "+version, func(t *testing.T) { restContainerEACLGet(ctx, t, clientPool) }) + 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) }) cancel() @@ -170,8 +172,6 @@ func getPool(ctx context.Context, t *testing.T, key *keys.PrivateKey) *pool.Pool } func restObjectPut(ctx context.Context, t *testing.T, clientPool *pool.Pool, cnrID *cid.ID) { - restrictByEACL(ctx, t, clientPool, cnrID) - bearer := &models.Bearer{ Object: []*models.Record{{ Operation: models.NewOperation(models.OperationPUT), @@ -238,8 +238,6 @@ func restObjectPut(ctx context.Context, t *testing.T, clientPool *pool.Pool, cnr } func restObjectGet(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *cid.ID) { - restrictByEACL(ctx, t, p, cnrID) - attributes := map[string]string{ object.AttributeFileName: "get-obj-name", "user-attribute": "user value", @@ -279,6 +277,41 @@ func restObjectGet(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *cid.I } } +func restObjectDelete(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *cid.ID) { + objID := createObject(ctx, t, p, cnrID, nil, []byte("some content")) + + bearer := &models.Bearer{ + Object: []*models.Record{{ + Operation: models.NewOperation(models.OperationDELETE), + 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) + + request, err := http.NewRequest(http.MethodDelete, testHost+"/v1/objects/"+cnrID.String()+"/"+objID.String(), nil) + require.NoError(t, err) + prepareCommonHeaders(request.Header, bearerToken) + + doRequest(t, httpClient, request, http.StatusNoContent, nil) + + var addr address.Address + addr.SetContainerID(cnrID) + addr.SetObjectID(objID) + + var prm pool.PrmObjectHead + prm.SetAddress(addr) + + _, err = p.HeadObject(ctx, prm) + require.Error(t, err) +} + func doRequest(t *testing.T, httpClient *http.Client, request *http.Request, expectedCode int, model interface{}) { resp, err := httpClient.Do(request) require.NoError(t, err) @@ -387,9 +420,11 @@ func restContainerEACLPut(ctx context.Context, t *testing.T, clientPool *pool.Po require.True(t, eacl.EqualTables(*expectedTable, *table)) } -func restContainerEACLGet(ctx context.Context, t *testing.T, clientPool *pool.Pool) { - cnrID := createContainer(ctx, t, clientPool, "for-eacl-get") - expectedTable := restrictByEACL(ctx, t, clientPool, cnrID) +func restContainerEACLGet(ctx context.Context, t *testing.T, p *pool.Pool, cnrID *cid.ID) { + var prm pool.PrmContainerEACL + prm.SetContainerID(*cnrID) + expectedTable, err := p.GetEACL(ctx, prm) + require.NoError(t, err) httpClient := &http.Client{Timeout: 60 * time.Second} @@ -459,8 +494,8 @@ func makeAuthTokenRequest(ctx context.Context, t *testing.T, bearer *models.Bear require.NoError(t, err) request = request.WithContext(ctx) request.Header.Add("Content-Type", "application/json") - request.Header.Add(XNeofsTokenScope, string(tokenType)) - request.Header.Add(XNeofsTokenSignatureKey, hexPubKey) + request.Header.Add(XBearerScope, string(tokenType)) + request.Header.Add(XBearerSignatureKey, hexPubKey) resp, err := httpClient.Do(request) require.NoError(t, err) @@ -564,9 +599,9 @@ func restContainerPut(ctx context.Context, t *testing.T, clientPool *pool.Pool) func prepareCommonHeaders(header http.Header, bearerToken *handlers.BearerToken) { header.Add("Content-Type", "application/json") - header.Add(XNeofsTokenSignature, bearerToken.Signature) + header.Add(XBearerSignature, bearerToken.Signature) header.Add("Authorization", "Bearer "+bearerToken.Token) - header.Add(XNeofsTokenSignatureKey, bearerToken.Key) + header.Add(XBearerSignatureKey, bearerToken.Key) } func createContainer(ctx context.Context, t *testing.T, clientPool *pool.Pool, name string) *cid.ID { diff --git a/gen/restapi/embedded_spec.go b/gen/restapi/embedded_spec.go index e33fe14..cc01b59 100644 --- a/gen/restapi/embedded_spec.go +++ b/gen/restapi/embedded_spec.go @@ -42,6 +42,9 @@ func init() { "summary": "Form bearer token to futher requests", "operationId": "auth", "parameters": [ + { + "$ref": "#/parameters/signatureKeyParam" + }, { "enum": [ "object", @@ -49,14 +52,7 @@ func init() { ], "type": "string", "description": "Supported operation scope for token", - "name": "X-Neofs-Token-Scope", - "in": "header", - "required": true - }, - { - "type": "string", - "description": "Public key of user", - "name": "X-Neofs-Token-Signature-Key", + "name": "X-Bearer-Scope", "in": "header", "required": true }, @@ -64,7 +60,7 @@ func init() { "type": "integer", "default": 100, "description": "Token lifetime in epoch", - "name": "X-Neofs-Token-Lifetime", + "name": "X-Bearer-Lifetime", "in": "header" }, { @@ -418,6 +414,21 @@ func init() { } } }, + "delete": { + "summary": "Remove object from NeoFS", + "operationId": "deleteObject", + "responses": { + "204": { + "description": "Successful deletion" + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, "parameters": [ { "$ref": "#/parameters/signatureParam" @@ -429,11 +440,7 @@ func init() { "$ref": "#/parameters/containerId" }, { - "type": "string", - "description": "Base58 encoded object id", - "name": "objectId", - "in": "path", - "required": true + "$ref": "#/parameters/objectId" } ] } @@ -814,7 +821,7 @@ func init() { "in": "path", "required": true }, - "ojectId": { + "objectId": { "type": "string", "description": "Base58 encoded object id", "name": "objectId", @@ -824,14 +831,14 @@ func init() { "signatureKeyParam": { "type": "string", "description": "Hex encoded the public part of the key that signed the bearer token", - "name": "X-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true }, "signatureParam": { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "name": "X-Bearer-Signature", "in": "header", "required": true } @@ -875,6 +882,13 @@ func init() { "summary": "Form bearer token to futher requests", "operationId": "auth", "parameters": [ + { + "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 + }, { "enum": [ "object", @@ -882,14 +896,7 @@ func init() { ], "type": "string", "description": "Supported operation scope for token", - "name": "X-Neofs-Token-Scope", - "in": "header", - "required": true - }, - { - "type": "string", - "description": "Public key of user", - "name": "X-Neofs-Token-Signature-Key", + "name": "X-Bearer-Scope", "in": "header", "required": true }, @@ -897,7 +904,7 @@ func init() { "type": "integer", "default": 100, "description": "Token lifetime in epoch", - "name": "X-Neofs-Token-Lifetime", + "name": "X-Bearer-Lifetime", "in": "header" }, { @@ -979,14 +986,14 @@ func init() { { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "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-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true }, @@ -1080,14 +1087,14 @@ func init() { { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "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-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true } @@ -1141,14 +1148,14 @@ func init() { { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "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-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true }, @@ -1260,14 +1267,14 @@ func init() { { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "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-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true } @@ -1292,18 +1299,33 @@ func init() { } } }, + "delete": { + "summary": "Remove object from NeoFS", + "operationId": "deleteObject", + "responses": { + "204": { + "description": "Successful deletion" + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, "parameters": [ { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "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-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true }, @@ -1700,7 +1722,7 @@ func init() { "in": "path", "required": true }, - "ojectId": { + "objectId": { "type": "string", "description": "Base58 encoded object id", "name": "objectId", @@ -1710,14 +1732,14 @@ func init() { "signatureKeyParam": { "type": "string", "description": "Hex encoded the public part of the key that signed the bearer token", - "name": "X-Neofs-Token-Signature-Key", + "name": "X-Bearer-Signature-Key", "in": "header", "required": true }, "signatureParam": { "type": "string", "description": "Base64 encoded signature for bearer token", - "name": "X-Neofs-Token-Signature", + "name": "X-Bearer-Signature", "in": "header", "required": true } diff --git a/gen/restapi/operations/auth_parameters.go b/gen/restapi/operations/auth_parameters.go index d5e8603..eaab093 100644 --- a/gen/restapi/operations/auth_parameters.go +++ b/gen/restapi/operations/auth_parameters.go @@ -27,11 +27,11 @@ func NewAuthParams() AuthParams { var ( // initialize parameters with default values - xNeofsTokenLifetimeDefault = int64(100) + xBearerLifetimeDefault = int64(100) ) return AuthParams{ - XNeofsTokenLifetime: &xNeofsTokenLifetimeDefault, + XBearerLifetime: &xBearerLifetimeDefault, } } @@ -48,17 +48,17 @@ type AuthParams struct { In: header Default: 100 */ - XNeofsTokenLifetime *int64 + XBearerLifetime *int64 /*Supported operation scope for token Required: true In: header */ - XNeofsTokenScope string - /*Public key of user + XBearerScope string + /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Bearer token Required: true In: body @@ -75,15 +75,15 @@ func (o *AuthParams) BindRequest(r *http.Request, route *middleware.MatchedRoute o.HTTPRequest = r - if err := o.bindXNeofsTokenLifetime(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Lifetime")], true, route.Formats); err != nil { + if err := o.bindXBearerLifetime(r.Header[http.CanonicalHeaderKey("X-Bearer-Lifetime")], true, route.Formats); err != nil { res = append(res, err) } - if err := o.bindXNeofsTokenScope(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Scope")], true, route.Formats); err != nil { + if err := o.bindXBearerScope(r.Header[http.CanonicalHeaderKey("X-Bearer-Scope")], 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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -120,8 +120,8 @@ func (o *AuthParams) BindRequest(r *http.Request, route *middleware.MatchedRoute return nil } -// bindXNeofsTokenLifetime binds and validates parameter XNeofsTokenLifetime from header. -func (o *AuthParams) bindXNeofsTokenLifetime(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerLifetime binds and validates parameter XBearerLifetime from header. +func (o *AuthParams) bindXBearerLifetime(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] @@ -136,17 +136,17 @@ func (o *AuthParams) bindXNeofsTokenLifetime(rawData []string, hasKey bool, form value, err := swag.ConvertInt64(raw) if err != nil { - return errors.InvalidType("X-Neofs-Token-Lifetime", "header", "int64", raw) + return errors.InvalidType("X-Bearer-Lifetime", "header", "int64", raw) } - o.XNeofsTokenLifetime = &value + o.XBearerLifetime = &value return nil } -// bindXNeofsTokenScope binds and validates parameter XNeofsTokenScope from header. -func (o *AuthParams) bindXNeofsTokenScope(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerScope binds and validates parameter XBearerScope from header. +func (o *AuthParams) bindXBearerScope(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Scope", "header", rawData) + return errors.Required("X-Bearer-Scope", "header", rawData) } var raw string if len(rawData) > 0 { @@ -155,32 +155,32 @@ func (o *AuthParams) bindXNeofsTokenScope(rawData []string, hasKey bool, formats // Required: true - if err := validate.RequiredString("X-Neofs-Token-Scope", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Scope", "header", raw); err != nil { return err } - o.XNeofsTokenScope = raw + o.XBearerScope = raw - if err := o.validateXNeofsTokenScope(formats); err != nil { + if err := o.validateXBearerScope(formats); err != nil { return err } return nil } -// validateXNeofsTokenScope carries on validations for parameter XNeofsTokenScope -func (o *AuthParams) validateXNeofsTokenScope(formats strfmt.Registry) error { +// validateXBearerScope carries on validations for parameter XBearerScope +func (o *AuthParams) validateXBearerScope(formats strfmt.Registry) error { - if err := validate.EnumCase("X-Neofs-Token-Scope", "header", o.XNeofsTokenScope, []interface{}{"object", "container"}, true); err != nil { + if err := validate.EnumCase("X-Bearer-Scope", "header", o.XBearerScope, []interface{}{"object", "container"}, true); err != nil { return err } return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *AuthParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *AuthParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -189,10 +189,10 @@ func (o *AuthParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/gen/restapi/operations/delete_container_parameters.go b/gen/restapi/operations/delete_container_parameters.go index 3665b2c..b5cb17b 100644 --- a/gen/restapi/operations/delete_container_parameters.go +++ b/gen/restapi/operations/delete_container_parameters.go @@ -35,12 +35,12 @@ type DeleteContainerParams struct { Required: true In: header */ - XNeofsTokenSignature string + XBearerSignature string /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Base58 encoded container id Required: true In: path @@ -57,11 +57,11 @@ func (o *DeleteContainerParams) BindRequest(r *http.Request, route *middleware.M o.HTTPRequest = r - if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil { + if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -75,10 +75,10 @@ func (o *DeleteContainerParams) BindRequest(r *http.Request, route *middleware.M return nil } -// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header. -func (o *DeleteContainerParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *DeleteContainerParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature", "header", rawData) + return errors.Required("X-Bearer-Signature", "header", rawData) } var raw string if len(rawData) > 0 { @@ -87,18 +87,18 @@ func (o *DeleteContainerParams) bindXNeofsTokenSignature(rawData []string, hasKe // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { return err } - o.XNeofsTokenSignature = raw + o.XBearerSignature = raw return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *DeleteContainerParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *DeleteContainerParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -107,10 +107,10 @@ func (o *DeleteContainerParams) bindXNeofsTokenSignatureKey(rawData []string, ha // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/gen/restapi/operations/delete_object.go b/gen/restapi/operations/delete_object.go new file mode 100644 index 0000000..333795d --- /dev/null +++ b/gen/restapi/operations/delete_object.go @@ -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" +) + +// DeleteObjectHandlerFunc turns a function with the right signature into a delete object handler +type DeleteObjectHandlerFunc func(DeleteObjectParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteObjectHandlerFunc) Handle(params DeleteObjectParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// DeleteObjectHandler interface for that can handle valid delete object params +type DeleteObjectHandler interface { + Handle(DeleteObjectParams, *models.Principal) middleware.Responder +} + +// NewDeleteObject creates a new http.Handler for the delete object operation +func NewDeleteObject(ctx *middleware.Context, handler DeleteObjectHandler) *DeleteObject { + return &DeleteObject{Context: ctx, Handler: handler} +} + +/* DeleteObject swagger:route DELETE /objects/{containerId}/{objectId} deleteObject + +Remove object from NeoFS + +*/ +type DeleteObject struct { + Context *middleware.Context + Handler DeleteObjectHandler +} + +func (o *DeleteObject) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteObjectParams() + 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) + +} diff --git a/gen/restapi/operations/delete_object_parameters.go b/gen/restapi/operations/delete_object_parameters.go new file mode 100644 index 0000000..57d9017 --- /dev/null +++ b/gen/restapi/operations/delete_object_parameters.go @@ -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" +) + +// NewDeleteObjectParams creates a new DeleteObjectParams object +// +// There are no default values defined in the spec. +func NewDeleteObjectParams() DeleteObjectParams { + + return DeleteObjectParams{} +} + +// DeleteObjectParams contains all the bound params for the delete object operation +// typically these are obtained from a http.Request +// +// swagger:parameters deleteObject +type DeleteObjectParams 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 + /*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 NewDeleteObjectParams() beforehand. +func (o *DeleteObjectParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + 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) + } + + 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 +} + +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *DeleteObjectParams) 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 *DeleteObjectParams) 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 *DeleteObjectParams) 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 *DeleteObjectParams) 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 +} diff --git a/gen/restapi/operations/delete_object_responses.go b/gen/restapi/operations/delete_object_responses.go new file mode 100644 index 0000000..ac6e64c --- /dev/null +++ b/gen/restapi/operations/delete_object_responses.go @@ -0,0 +1,80 @@ +// 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" +) + +// DeleteObjectNoContentCode is the HTTP code returned for type DeleteObjectNoContent +const DeleteObjectNoContentCode int = 204 + +/*DeleteObjectNoContent Successful deletion + +swagger:response deleteObjectNoContent +*/ +type DeleteObjectNoContent struct { +} + +// NewDeleteObjectNoContent creates DeleteObjectNoContent with default headers values +func NewDeleteObjectNoContent() *DeleteObjectNoContent { + + return &DeleteObjectNoContent{} +} + +// WriteResponse to the client +func (o *DeleteObjectNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(204) +} + +// DeleteObjectBadRequestCode is the HTTP code returned for type DeleteObjectBadRequest +const DeleteObjectBadRequestCode int = 400 + +/*DeleteObjectBadRequest Bad request + +swagger:response deleteObjectBadRequest +*/ +type DeleteObjectBadRequest struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteObjectBadRequest creates DeleteObjectBadRequest with default headers values +func NewDeleteObjectBadRequest() *DeleteObjectBadRequest { + + return &DeleteObjectBadRequest{} +} + +// WithPayload adds the payload to the delete object bad request response +func (o *DeleteObjectBadRequest) WithPayload(payload models.Error) *DeleteObjectBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete object bad request response +func (o *DeleteObjectBadRequest) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteObjectBadRequest) 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 + } +} diff --git a/gen/restapi/operations/get_object_info_parameters.go b/gen/restapi/operations/get_object_info_parameters.go index 2aba4c1..934b7c6 100644 --- a/gen/restapi/operations/get_object_info_parameters.go +++ b/gen/restapi/operations/get_object_info_parameters.go @@ -35,12 +35,12 @@ type GetObjectInfoParams struct { Required: true In: header */ - XNeofsTokenSignature string + XBearerSignature string /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Base58 encoded container id Required: true In: path @@ -62,11 +62,11 @@ func (o *GetObjectInfoParams) BindRequest(r *http.Request, route *middleware.Mat o.HTTPRequest = r - if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil { + if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -85,10 +85,10 @@ func (o *GetObjectInfoParams) BindRequest(r *http.Request, route *middleware.Mat return nil } -// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header. -func (o *GetObjectInfoParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *GetObjectInfoParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature", "header", rawData) + return errors.Required("X-Bearer-Signature", "header", rawData) } var raw string if len(rawData) > 0 { @@ -97,18 +97,18 @@ func (o *GetObjectInfoParams) bindXNeofsTokenSignature(rawData []string, hasKey // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { return err } - o.XNeofsTokenSignature = raw + o.XBearerSignature = raw return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *GetObjectInfoParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *GetObjectInfoParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -117,10 +117,10 @@ func (o *GetObjectInfoParams) bindXNeofsTokenSignatureKey(rawData []string, hasK // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/gen/restapi/operations/neofs_rest_gw_api.go b/gen/restapi/operations/neofs_rest_gw_api.go index 8fa1ed2..5798828 100644 --- a/gen/restapi/operations/neofs_rest_gw_api.go +++ b/gen/restapi/operations/neofs_rest_gw_api.go @@ -50,6 +50,9 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI { DeleteContainerHandler: DeleteContainerHandlerFunc(func(params DeleteContainerParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation DeleteContainer has not yet been implemented") }), + DeleteObjectHandler: DeleteObjectHandlerFunc(func(params DeleteObjectParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation DeleteObject has not yet been implemented") + }), GetContainerHandler: GetContainerHandlerFunc(func(params GetContainerParams) middleware.Responder { return middleware.NotImplemented("operation GetContainer has not yet been implemented") }), @@ -125,6 +128,8 @@ type NeofsRestGwAPI struct { AuthHandler AuthHandler // DeleteContainerHandler sets the operation handler for the delete container operation DeleteContainerHandler DeleteContainerHandler + // DeleteObjectHandler sets the operation handler for the delete object operation + DeleteObjectHandler DeleteObjectHandler // GetContainerHandler sets the operation handler for the get container operation GetContainerHandler GetContainerHandler // GetContainerEACLHandler sets the operation handler for the get container e ACL operation @@ -226,6 +231,9 @@ func (o *NeofsRestGwAPI) Validate() error { if o.DeleteContainerHandler == nil { unregistered = append(unregistered, "DeleteContainerHandler") } + if o.DeleteObjectHandler == nil { + unregistered = append(unregistered, "DeleteObjectHandler") + } if o.GetContainerHandler == nil { unregistered = append(unregistered, "GetContainerHandler") } @@ -354,6 +362,10 @@ func (o *NeofsRestGwAPI) initHandlerCache() { o.handlers["DELETE"] = make(map[string]http.Handler) } o.handlers["DELETE"]["/containers/{containerId}"] = NewDeleteContainer(o.context, o.DeleteContainerHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/objects/{containerId}/{objectId}"] = NewDeleteObject(o.context, o.DeleteObjectHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/gen/restapi/operations/put_container_e_acl_parameters.go b/gen/restapi/operations/put_container_e_acl_parameters.go index 9ee77a5..1e6aad6 100644 --- a/gen/restapi/operations/put_container_e_acl_parameters.go +++ b/gen/restapi/operations/put_container_e_acl_parameters.go @@ -40,12 +40,12 @@ type PutContainerEACLParams struct { Required: true In: header */ - XNeofsTokenSignature string + XBearerSignature string /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Base58 encoded container id Required: true In: path @@ -67,11 +67,11 @@ func (o *PutContainerEACLParams) BindRequest(r *http.Request, route *middleware. o.HTTPRequest = r - if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil { + if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -113,10 +113,10 @@ func (o *PutContainerEACLParams) BindRequest(r *http.Request, route *middleware. return nil } -// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header. -func (o *PutContainerEACLParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *PutContainerEACLParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature", "header", rawData) + return errors.Required("X-Bearer-Signature", "header", rawData) } var raw string if len(rawData) > 0 { @@ -125,18 +125,18 @@ func (o *PutContainerEACLParams) bindXNeofsTokenSignature(rawData []string, hasK // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { return err } - o.XNeofsTokenSignature = raw + o.XBearerSignature = raw return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *PutContainerEACLParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *PutContainerEACLParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -145,10 +145,10 @@ func (o *PutContainerEACLParams) bindXNeofsTokenSignatureKey(rawData []string, h // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/gen/restapi/operations/put_container_parameters.go b/gen/restapi/operations/put_container_parameters.go index 82cb3ab..11ca2b9 100644 --- a/gen/restapi/operations/put_container_parameters.go +++ b/gen/restapi/operations/put_container_parameters.go @@ -46,12 +46,12 @@ type PutContainerParams struct { Required: true In: header */ - XNeofsTokenSignature string + XBearerSignature string /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Container info Required: true In: body @@ -75,11 +75,11 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc qs := runtime.Values(r.URL.Query()) - if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil { + if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -121,10 +121,10 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc return nil } -// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header. -func (o *PutContainerParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *PutContainerParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature", "header", rawData) + return errors.Required("X-Bearer-Signature", "header", rawData) } var raw string if len(rawData) > 0 { @@ -133,18 +133,18 @@ func (o *PutContainerParams) bindXNeofsTokenSignature(rawData []string, hasKey b // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { return err } - o.XNeofsTokenSignature = raw + o.XBearerSignature = raw return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *PutContainerParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *PutContainerParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -153,10 +153,10 @@ 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-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/gen/restapi/operations/put_object_parameters.go b/gen/restapi/operations/put_object_parameters.go index ef2d910..f2b7a17 100644 --- a/gen/restapi/operations/put_object_parameters.go +++ b/gen/restapi/operations/put_object_parameters.go @@ -38,12 +38,12 @@ type PutObjectParams struct { Required: true In: header */ - XNeofsTokenSignature string + XBearerSignature string /*Hex encoded the public part of the key that signed the bearer token Required: true In: header */ - XNeofsTokenSignatureKey string + XBearerSignatureKey string /*Object info to upload Required: true In: body @@ -60,11 +60,11 @@ func (o *PutObjectParams) BindRequest(r *http.Request, route *middleware.Matched o.HTTPRequest = r - if err := o.bindXNeofsTokenSignature(r.Header[http.CanonicalHeaderKey("X-Neofs-Token-Signature")], true, route.Formats); err != nil { + if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-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 { + if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil { res = append(res, err) } @@ -101,10 +101,10 @@ func (o *PutObjectParams) BindRequest(r *http.Request, route *middleware.Matched return nil } -// bindXNeofsTokenSignature binds and validates parameter XNeofsTokenSignature from header. -func (o *PutObjectParams) bindXNeofsTokenSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignature binds and validates parameter XBearerSignature from header. +func (o *PutObjectParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature", "header", rawData) + return errors.Required("X-Bearer-Signature", "header", rawData) } var raw string if len(rawData) > 0 { @@ -113,18 +113,18 @@ func (o *PutObjectParams) bindXNeofsTokenSignature(rawData []string, hasKey bool // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { return err } - o.XNeofsTokenSignature = raw + o.XBearerSignature = raw return nil } -// bindXNeofsTokenSignatureKey binds and validates parameter XNeofsTokenSignatureKey from header. -func (o *PutObjectParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { +// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. +func (o *PutObjectParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { if !hasKey { - return errors.Required("X-Neofs-Token-Signature-Key", "header", rawData) + return errors.Required("X-Bearer-Signature-Key", "header", rawData) } var raw string if len(rawData) > 0 { @@ -133,10 +133,10 @@ func (o *PutObjectParams) bindXNeofsTokenSignatureKey(rawData []string, hasKey b // Required: true - if err := validate.RequiredString("X-Neofs-Token-Signature-Key", "header", raw); err != nil { + if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { return err } - o.XNeofsTokenSignatureKey = raw + o.XBearerSignatureKey = raw return nil } diff --git a/handlers/api.go b/handlers/api.go index cf8eafb..a2235e3 100644 --- a/handlers/api.go +++ b/handlers/api.go @@ -65,6 +65,7 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler { api.PutObjectHandler = operations.PutObjectHandlerFunc(a.PutObjects) api.GetObjectInfoHandler = operations.GetObjectInfoHandlerFunc(a.GetObjectInfo) + api.DeleteObjectHandler = operations.DeleteObjectHandlerFunc(a.DeleteObject) api.PutContainerHandler = operations.PutContainerHandlerFunc(a.PutContainers) api.GetContainerHandler = operations.GetContainerHandlerFunc(a.GetContainer) diff --git a/handlers/auth.go b/handlers/auth.go index 22ab16d..2b77a43 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -24,7 +24,7 @@ func (a *API) PostAuth(params operations.AuthParams) middleware.Responder { resp *models.TokenResponse ) - if params.XNeofsTokenScope == "object" { + if params.XBearerScope == "object" { resp, err = prepareObjectToken(params, a.pool) } else { resp, err = prepareContainerTokens(params, a.pool, a.key.PublicKey()) @@ -45,7 +45,7 @@ func prepareObjectToken(params operations.AuthParams, pool *pool.Pool) (*models. } btoken.SetOwner(pool.OwnerID()) - iat, exp, err := getTokenLifetime(ctx, pool, params.XNeofsTokenLifetime) + iat, exp, err := getTokenLifetime(ctx, pool, params.XBearerLifetime) if err != nil { return nil, fmt.Errorf("couldn't get lifetime: %w", err) } @@ -66,12 +66,12 @@ func prepareObjectToken(params operations.AuthParams, pool *pool.Pool) (*models. func prepareContainerTokens(params operations.AuthParams, pool *pool.Pool, key *keys.PublicKey) (*models.TokenResponse, error) { ctx := params.HTTPRequest.Context() - iat, exp, err := getTokenLifetime(ctx, pool, params.XNeofsTokenLifetime) + iat, exp, err := getTokenLifetime(ctx, pool, params.XBearerLifetime) if err != nil { return nil, fmt.Errorf("couldn't get lifetime: %w", err) } - ownerKey, err := keys.NewPublicKeyFromString(params.XNeofsTokenSignatureKey) + ownerKey, err := keys.NewPublicKeyFromString(params.XBearerSignatureKey) if err != nil { return nil, fmt.Errorf("invalid singature key: %w", err) } diff --git a/handlers/containers.go b/handlers/containers.go index bb75d72..d37e94a 100644 --- a/handlers/containers.go +++ b/handlers/containers.go @@ -4,7 +4,6 @@ import ( "context" "encoding/base64" "fmt" - "github.com/nspcc-dev/neofs-sdk-go/owner" "net/http" "strconv" "strings" @@ -19,6 +18,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/acl" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + "github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/policy" "github.com/nspcc-dev/neofs-sdk-go/pool" "github.com/nspcc-dev/neofs-sdk-go/session" @@ -34,8 +34,8 @@ const ( func (a *API) PutContainers(params operations.PutContainerParams, principal *models.Principal) middleware.Responder { bt := &BearerToken{ Token: string(*principal), - Signature: params.XNeofsTokenSignature, - Key: params.XNeofsTokenSignatureKey, + Signature: params.XBearerSignature, + Key: params.XBearerSignatureKey, } stoken, err := prepareSessionToken(bt) if err != nil { @@ -92,8 +92,8 @@ func (a *API) PutContainerEACL(params operations.PutContainerEACLParams, princip bt := &BearerToken{ Token: string(*principal), - Signature: params.XNeofsTokenSignature, - Key: params.XNeofsTokenSignatureKey, + Signature: params.XBearerSignature, + Key: params.XBearerSignatureKey, } stoken, err := prepareSessionToken(bt) if err != nil { @@ -180,8 +180,8 @@ func (a *API) ListContainer(params operations.ListContainersParams) middleware.R func (a *API) DeleteContainer(params operations.DeleteContainerParams, principal *models.Principal) middleware.Responder { bt := &BearerToken{ Token: string(*principal), - Signature: params.XNeofsTokenSignature, - Key: params.XNeofsTokenSignatureKey, + Signature: params.XBearerSignature, + Key: params.XBearerSignatureKey, } stoken, err := prepareSessionToken(bt) if err != nil { diff --git a/handlers/objects.go b/handlers/objects.go index ef04be1..c28129e 100644 --- a/handlers/objects.go +++ b/handlers/objects.go @@ -4,10 +4,6 @@ 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" @@ -16,8 +12,11 @@ import ( "github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" + "github.com/nspcc-dev/neofs-sdk-go/object/address" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/pool" "github.com/nspcc-dev/neofs-sdk-go/token" + "go.uber.org/zap" ) // PutObjects handler that uploads object to NeoFS. @@ -25,13 +24,7 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr errorResponse := operations.NewPutObjectBadRequest() ctx := params.HTTPRequest.Context() - bt := &BearerToken{ - Token: string(*principal), - Signature: params.XNeofsTokenSignature, - Key: params.XNeofsTokenSignatureKey, - } - - btoken, err := prepareBearerToken(bt) + btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey) if err != nil { return errorResponse.WithPayload(models.Error(err.Error())) } @@ -83,32 +76,18 @@ func (a *API) GetObjectInfo(params operations.GetObjectInfoParams, principal *mo 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") + addr, err := parseAddress(params.ContainerID, params.ObjectID) + if err != nil { + a.log.Error("invalid address", zap.Error(err)) + return errorResponse.WithPayload("invalid address") } - bt := &BearerToken{ - Token: string(*principal), - Signature: params.XNeofsTokenSignature, - Key: params.XNeofsTokenSignatureKey, - } - - btoken, err := prepareBearerToken(bt) + btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey) 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) @@ -133,8 +112,64 @@ func (a *API) GetObjectInfo(params operations.GetObjectInfoParams, principal *mo return operations.NewGetObjectInfoOK().WithPayload(&resp) } +// DeleteObject handler that removes object from NeoFS. +func (a *API) DeleteObject(params operations.DeleteObjectParams, principal *models.Principal) middleware.Responder { + errorResponse := operations.NewDeleteObjectBadRequest() + ctx := params.HTTPRequest.Context() + + addr, err := parseAddress(params.ContainerID, params.ObjectID) + if err != nil { + a.log.Error("invalid address", zap.Error(err)) + return errorResponse.WithPayload("invalid address") + } + + btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey) + if err != nil { + a.log.Error("failed to get bearer token", zap.Error(err)) + return errorResponse.WithPayload(NewError(err)) + } + + var prm pool.PrmObjectDelete + prm.SetAddress(*addr) + prm.UseBearer(btoken) + + if err = a.pool.DeleteObject(ctx, prm); err != nil { + a.log.Error("failed to delete object", zap.Error(err)) + return errorResponse.WithPayload(NewError(err)) + } + + return operations.NewDeleteObjectNoContent() +} + +func parseAddress(containerID, objectID string) (*address.Address, error) { + var cnrID cid.ID + if err := cnrID.Parse(containerID); err != nil { + return nil, fmt.Errorf("invalid container id: %w", err) + } + var objID oid.ID + if err := objID.Parse(objectID); err != nil { + return nil, fmt.Errorf("invalid object id: %w", err) + } + + addr := address.NewAddress() + addr.SetContainerID(&cnrID) + addr.SetObjectID(&objID) + + return addr, nil +} + +func getBearerToken(token *models.Principal, signature, key string) (*token.BearerToken, error) { + bt := &BearerToken{ + Token: string(*token), + Signature: signature, + Key: key, + } + + return prepareBearerToken(bt) +} + func prepareBearerToken(bt *BearerToken) (*token.BearerToken, error) { - btoken, err := getBearerToken(bt.Token) + btoken, err := parseBearerToken(bt.Token) if err != nil { return nil, fmt.Errorf("could not fetch bearer token: %w", err) } @@ -158,7 +193,7 @@ func prepareBearerToken(bt *BearerToken) (*token.BearerToken, error) { return btoken, btoken.VerifySignature() } -func getBearerToken(auth string) (*token.BearerToken, error) { +func parseBearerToken(auth string) (*token.BearerToken, error) { data, err := base64.StdEncoding.DecodeString(auth) if err != nil { return nil, fmt.Errorf("can't base64-decode bearer token: %w", err) diff --git a/spec/rest.yaml b/spec/rest.yaml index 4102dfe..d96d2db 100644 --- a/spec/rest.yaml +++ b/spec/rest.yaml @@ -23,13 +23,13 @@ security: parameters: signatureParam: in: header - name: X-Neofs-Token-Signature + name: X-Bearer-Signature description: Base64 encoded signature for bearer token type: string required: true signatureKeyParam: in: header - name: X-Neofs-Token-Signature-Key + name: X-Bearer-Signature-Key description: Hex encoded the public part of the key that signed the bearer token type: string required: true @@ -39,7 +39,7 @@ parameters: type: string required: true description: Base58 encoded container id - ojectId: + objectId: in: path name: objectId type: string @@ -53,22 +53,18 @@ paths: summary: Form bearer token to futher requests security: [ ] parameters: + - $ref: '#/parameters/signatureKeyParam' - in: header description: Supported operation scope for token - name: X-Neofs-Token-Scope + name: X-Bearer-Scope type: string enum: - object - container required: true - - in: header - description: Public key of user - name: X-Neofs-Token-Signature-Key - type: string - required: true - in: header description: Token lifetime in epoch - name: X-Neofs-Token-Lifetime + name: X-Bearer-Lifetime type: integer default: 100 - in: body @@ -149,11 +145,7 @@ paths: - $ref: '#/parameters/signatureParam' - $ref: '#/parameters/signatureKeyParam' - $ref: '#/parameters/containerId' - - in: path - name: objectId - type: string - required: true - description: Base58 encoded object id + - $ref: '#/parameters/objectId' get: operationId: getObjectInfo summary: Get object info by address and @@ -166,6 +158,16 @@ paths: description: Bad request schema: $ref: '#/definitions/Error' + delete: + operationId: deleteObject + summary: Remove object from NeoFS + responses: + 204: + description: Successful deletion + 400: + description: Bad request + schema: + $ref: '#/definitions/Error' /containers: put: