From 8d5d19f3c421edb12e93e89fbb9bcb3cbda5e382 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 18 Aug 2022 18:41:33 +0300 Subject: [PATCH] [#32] Support full bearer token for object routes Signed-off-by: Denis Kirillov --- gen/restapi/embedded_spec.go | 114 ++++++++++++------ .../operations/delete_container_parameters.go | 29 ++--- .../operations/delete_object_parameters.go | 67 +++++++--- .../form_binary_bearer_parameters.go | 29 ++--- .../operations/get_object_info_parameters.go | 65 +++++++--- .../put_container_e_acl_parameters.go | 28 ++--- .../operations/put_container_parameters.go | 28 ++--- .../operations/put_object_parameters.go | 66 +++++++--- .../operations/search_objects_parameters.go | 69 ++++++++--- handlers/auth.go | 8 +- handlers/auth_test.go | 2 +- handlers/containers.go | 36 +++--- handlers/objects.go | 71 ++++++++--- handlers/util.go | 36 ++++++ spec/rest.yaml | 14 ++- 15 files changed, 434 insertions(+), 228 deletions(-) diff --git a/gen/restapi/embedded_spec.go b/gen/restapi/embedded_spec.go index 2753ab2..1d22aa4 100644 --- a/gen/restapi/embedded_spec.go +++ b/gen/restapi/embedded_spec.go @@ -526,6 +526,9 @@ func init() { { "$ref": "#/parameters/signatureScheme" }, + { + "$ref": "#/parameters/fullBearerToken" + }, { "description": "Object info to upload", "name": "object", @@ -591,6 +594,9 @@ func init() { { "$ref": "#/parameters/signatureScheme" }, + { + "$ref": "#/parameters/fullBearerToken" + }, { "type": "integer", "default": 0, @@ -674,6 +680,9 @@ func init() { { "$ref": "#/parameters/signatureScheme" }, + { + "$ref": "#/parameters/fullBearerToken" + }, { "type": "integer", "description": "Range offset to start reading data.", @@ -728,6 +737,9 @@ func init() { }, { "$ref": "#/parameters/signatureScheme" + }, + { + "$ref": "#/parameters/fullBearerToken" } ], "responses": { @@ -1575,6 +1587,13 @@ func init() { "in": "path", "required": true }, + "fullBearerToken": { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" + }, "objectId": { "type": "string", "description": "Base58 encoded object id.", @@ -1586,15 +1605,13 @@ func init() { "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 + "in": "header" }, "signatureParam": { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, "signatureScheme": { "type": "boolean", @@ -1769,15 +1786,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -1867,15 +1882,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -1986,15 +1999,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2087,15 +2098,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2179,15 +2188,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2196,6 +2203,13 @@ func init() { "name": "walletConnect", "in": "query" }, + { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" + }, { "description": "Object info to upload", "name": "object", @@ -2256,15 +2270,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2273,6 +2285,13 @@ func init() { "name": "walletConnect", "in": "query" }, + { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" + }, { "minimum": 0, "type": "integer", @@ -2356,15 +2375,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2373,6 +2390,13 @@ func init() { "name": "walletConnect", "in": "query" }, + { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" + }, { "minimum": 0, "type": "integer", @@ -2425,15 +2449,13 @@ func init() { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, { "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 + "in": "header" }, { "type": "boolean", @@ -2441,6 +2463,13 @@ func init() { "description": "Use wallet connect signature scheme or native NeoFS signature.", "name": "walletConnect", "in": "query" + }, + { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" } ], "responses": { @@ -3296,6 +3325,13 @@ func init() { "in": "path", "required": true }, + "fullBearerToken": { + "type": "boolean", + "default": false, + "description": "Provided bearer token is final or gate should assemble it using signature.", + "name": "fullBearer", + "in": "query" + }, "objectId": { "type": "string", "description": "Base58 encoded object id.", @@ -3307,15 +3343,13 @@ func init() { "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 + "in": "header" }, "signatureParam": { "type": "string", "description": "Base64 encoded signature for bearer token.", "name": "X-Bearer-Signature", - "in": "header", - "required": true + "in": "header" }, "signatureScheme": { "type": "boolean", diff --git a/gen/restapi/operations/delete_container_parameters.go b/gen/restapi/operations/delete_container_parameters.go index 3d79698..e976d30 100644 --- a/gen/restapi/operations/delete_container_parameters.go +++ b/gen/restapi/operations/delete_container_parameters.go @@ -13,7 +13,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" - "github.com/go-openapi/validate" ) // NewDeleteContainerParams creates a new DeleteContainerParams object @@ -41,15 +40,13 @@ type DeleteContainerParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Base58 encoded container id. Required: true In: path @@ -98,40 +95,34 @@ func (o *DeleteContainerParams) BindRequest(r *http.Request, route *middleware.M // 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-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // 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-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw return nil } diff --git a/gen/restapi/operations/delete_object_parameters.go b/gen/restapi/operations/delete_object_parameters.go index 3da8072..9afb564 100644 --- a/gen/restapi/operations/delete_object_parameters.go +++ b/gen/restapi/operations/delete_object_parameters.go @@ -13,7 +13,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" - "github.com/go-openapi/validate" ) // NewDeleteObjectParams creates a new DeleteObjectParams object @@ -23,10 +22,14 @@ func NewDeleteObjectParams() DeleteObjectParams { var ( // initialize parameters with default values + fullBearerDefault = bool(false) + walletConnectDefault = bool(false) ) return DeleteObjectParams{ + FullBearer: &fullBearerDefault, + WalletConnect: &walletConnectDefault, } } @@ -41,20 +44,23 @@ type DeleteObjectParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Base58 encoded container id. Required: true In: path */ ContainerID string + /*Provided bearer token is final or gate should assemble it using signature. + In: query + Default: false + */ + FullBearer *bool /*Base58 encoded object id. Required: true In: path @@ -91,6 +97,11 @@ func (o *DeleteObjectParams) BindRequest(r *http.Request, route *middleware.Matc res = append(res, err) } + qFullBearer, qhkFullBearer, _ := qs.GetOK("fullBearer") + if err := o.bindFullBearer(qFullBearer, qhkFullBearer, 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) @@ -108,40 +119,34 @@ func (o *DeleteObjectParams) BindRequest(r *http.Request, route *middleware.Matc // 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 + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + 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 + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw return nil } @@ -160,6 +165,30 @@ func (o *DeleteObjectParams) bindContainerID(rawData []string, hasKey bool, form return nil } +// bindFullBearer binds and validates parameter FullBearer from query. +func (o *DeleteObjectParams) bindFullBearer(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewDeleteObjectParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("fullBearer", "query", "bool", raw) + } + o.FullBearer = &value + + 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 diff --git a/gen/restapi/operations/form_binary_bearer_parameters.go b/gen/restapi/operations/form_binary_bearer_parameters.go index 8df3416..3b18f87 100644 --- a/gen/restapi/operations/form_binary_bearer_parameters.go +++ b/gen/restapi/operations/form_binary_bearer_parameters.go @@ -13,7 +13,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" - "github.com/go-openapi/validate" ) // NewFormBinaryBearerParams creates a new FormBinaryBearerParams object @@ -41,15 +40,13 @@ type FormBinaryBearerParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Use wallet connect signature scheme or native NeoFS signature. In: query Default: false @@ -88,40 +85,34 @@ func (o *FormBinaryBearerParams) BindRequest(r *http.Request, route *middleware. // bindXBearerSignature binds and validates parameter XBearerSignature from header. func (o *FormBinaryBearerParams) 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 + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. func (o *FormBinaryBearerParams) 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 + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw return nil } diff --git a/gen/restapi/operations/get_object_info_parameters.go b/gen/restapi/operations/get_object_info_parameters.go index 5e944c5..9641587 100644 --- a/gen/restapi/operations/get_object_info_parameters.go +++ b/gen/restapi/operations/get_object_info_parameters.go @@ -23,12 +23,15 @@ func NewGetObjectInfoParams() GetObjectInfoParams { var ( // initialize parameters with default values + fullBearerDefault = bool(false) maxPayloadSizeDefault = int64(4.194304e+06) walletConnectDefault = bool(false) ) return GetObjectInfoParams{ + FullBearer: &fullBearerDefault, + MaxPayloadSize: &maxPayloadSizeDefault, WalletConnect: &walletConnectDefault, @@ -45,20 +48,23 @@ type GetObjectInfoParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Base58 encoded container id. Required: true In: path */ ContainerID string + /*Provided bearer token is final or gate should assemble it using signature. + In: query + Default: false + */ + FullBearer *bool /*Max payload size (in bytes) that can be included in the response. If the actual size is greater than this params the payload won't be included in the response. @@ -114,6 +120,11 @@ func (o *GetObjectInfoParams) BindRequest(r *http.Request, route *middleware.Mat res = append(res, err) } + qFullBearer, qhkFullBearer, _ := qs.GetOK("fullBearer") + if err := o.bindFullBearer(qFullBearer, qhkFullBearer, route.Formats); err != nil { + res = append(res, err) + } + qMaxPayloadSize, qhkMaxPayloadSize, _ := qs.GetOK("max-payload-size") if err := o.bindMaxPayloadSize(qMaxPayloadSize, qhkMaxPayloadSize, route.Formats); err != nil { res = append(res, err) @@ -146,40 +157,34 @@ func (o *GetObjectInfoParams) BindRequest(r *http.Request, route *middleware.Mat // 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-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // 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-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw return nil } @@ -198,6 +203,30 @@ func (o *GetObjectInfoParams) bindContainerID(rawData []string, hasKey bool, for return nil } +// bindFullBearer binds and validates parameter FullBearer from query. +func (o *GetObjectInfoParams) bindFullBearer(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetObjectInfoParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("fullBearer", "query", "bool", raw) + } + o.FullBearer = &value + + return nil +} + // bindMaxPayloadSize binds and validates parameter MaxPayloadSize from query. func (o *GetObjectInfoParams) bindMaxPayloadSize(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string diff --git a/gen/restapi/operations/put_container_e_acl_parameters.go b/gen/restapi/operations/put_container_e_acl_parameters.go index 06de0dc..03d3922 100644 --- a/gen/restapi/operations/put_container_e_acl_parameters.go +++ b/gen/restapi/operations/put_container_e_acl_parameters.go @@ -45,15 +45,13 @@ type PutContainerEACLParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Base58 encoded container id. Required: true In: path @@ -135,40 +133,34 @@ func (o *PutContainerEACLParams) BindRequest(r *http.Request, route *middleware. // 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-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // 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-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = 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 aa9c423..9422fad 100644 --- a/gen/restapi/operations/put_container_parameters.go +++ b/gen/restapi/operations/put_container_parameters.go @@ -48,15 +48,13 @@ type PutContainerParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Container info Required: true In: body @@ -138,40 +136,34 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc // 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-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // 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-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = 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 5d9c0cb..132d647 100644 --- a/gen/restapi/operations/put_object_parameters.go +++ b/gen/restapi/operations/put_object_parameters.go @@ -27,10 +27,14 @@ func NewPutObjectParams() PutObjectParams { var ( // initialize parameters with default values + fullBearerDefault = bool(false) + walletConnectDefault = bool(false) ) return PutObjectParams{ + FullBearer: &fullBearerDefault, + WalletConnect: &walletConnectDefault, } } @@ -45,15 +49,18 @@ type PutObjectParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string + /*Provided bearer token is final or gate should assemble it using signature. + In: query + Default: false + */ + FullBearer *bool /*Object info to upload Required: true In: body @@ -85,6 +92,11 @@ func (o *PutObjectParams) BindRequest(r *http.Request, route *middleware.Matched res = append(res, err) } + qFullBearer, qhkFullBearer, _ := qs.GetOK("fullBearer") + if err := o.bindFullBearer(qFullBearer, qhkFullBearer, route.Formats); err != nil { + res = append(res, err) + } + if runtime.HasBody(r) { defer r.Body.Close() var body models.ObjectUpload @@ -125,40 +137,58 @@ func (o *PutObjectParams) BindRequest(r *http.Request, route *middleware.Matched // 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-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // 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-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw + + return nil +} + +// bindFullBearer binds and validates parameter FullBearer from query. +func (o *PutObjectParams) bindFullBearer(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutObjectParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("fullBearer", "query", "bool", raw) + } + o.FullBearer = &value return nil } diff --git a/gen/restapi/operations/search_objects_parameters.go b/gen/restapi/operations/search_objects_parameters.go index 2828c1f..1f9bfa9 100644 --- a/gen/restapi/operations/search_objects_parameters.go +++ b/gen/restapi/operations/search_objects_parameters.go @@ -27,13 +27,16 @@ func NewSearchObjectsParams() SearchObjectsParams { var ( // initialize parameters with default values - limitDefault = int64(100) - offsetDefault = int64(0) + fullBearerDefault = bool(false) + limitDefault = int64(100) + offsetDefault = int64(0) walletConnectDefault = bool(false) ) return SearchObjectsParams{ + FullBearer: &fullBearerDefault, + Limit: &limitDefault, Offset: &offsetDefault, @@ -52,20 +55,23 @@ type SearchObjectsParams struct { HTTPRequest *http.Request `json:"-"` /*Base64 encoded signature for bearer token. - Required: true In: header */ - XBearerSignature string + XBearerSignature *string /*Hex encoded the public part of the key that signed the bearer token. - Required: true In: header */ - XBearerSignatureKey string + XBearerSignatureKey *string /*Base58 encoded container id. Required: true In: path */ ContainerID string + /*Provided bearer token is final or gate should assemble it using signature. + In: query + Default: false + */ + FullBearer *bool /*The numbers of containers to return. Maximum: 10000 Minimum: 1 @@ -115,6 +121,11 @@ func (o *SearchObjectsParams) BindRequest(r *http.Request, route *middleware.Mat res = append(res, err) } + qFullBearer, qhkFullBearer, _ := qs.GetOK("fullBearer") + if err := o.bindFullBearer(qFullBearer, qhkFullBearer, route.Formats); err != nil { + res = append(res, err) + } + qLimit, qhkLimit, _ := qs.GetOK("limit") if err := o.bindLimit(qLimit, qhkLimit, route.Formats); err != nil { res = append(res, err) @@ -165,40 +176,34 @@ func (o *SearchObjectsParams) BindRequest(r *http.Request, route *middleware.Mat // bindXBearerSignature binds and validates parameter XBearerSignature from header. func (o *SearchObjectsParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error { - if !hasKey { - return errors.Required("X-Bearer-Signature", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignature = raw + o.XBearerSignature = &raw return nil } // bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header. func (o *SearchObjectsParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error { - if !hasKey { - return errors.Required("X-Bearer-Signature-Key", "header", rawData) - } var raw string if len(rawData) > 0 { raw = rawData[len(rawData)-1] } - // Required: true + // Required: false - if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil { - return err + if raw == "" { // empty values pass all other validations + return nil } - o.XBearerSignatureKey = raw + o.XBearerSignatureKey = &raw return nil } @@ -217,6 +222,30 @@ func (o *SearchObjectsParams) bindContainerID(rawData []string, hasKey bool, for return nil } +// bindFullBearer binds and validates parameter FullBearer from query. +func (o *SearchObjectsParams) bindFullBearer(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewSearchObjectsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("fullBearer", "query", "bool", raw) + } + o.FullBearer = &value + + return nil +} + // bindLimit binds and validates parameter Limit from query. func (o *SearchObjectsParams) bindLimit(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string diff --git a/handlers/auth.go b/handlers/auth.go index 02a9546..a33f047 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -106,7 +106,13 @@ func (a *API) PostAuth(params operations.AuthParams) middleware.Responder { // FormBinaryBearer handler that forms binary bearer token using headers with body and signature. func (a *API) FormBinaryBearer(params operations.FormBinaryBearerParams, principal *models.Principal) middleware.Responder { - btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect) + bearerHeaders, err := prepareBearerTokenHeaders(params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect, false) + if err != nil { + resp := a.logAndGetErrorResponse("invalid bearer headers", err) + return operations.NewFormBinaryBearerBadRequest().WithPayload(resp) + } + + btoken, err := getBearerToken(principal, bearerHeaders) if err != nil { resp := a.logAndGetErrorResponse("invalid bearer token", err) return operations.NewFormBinaryBearerBadRequest().WithPayload(resp) diff --git a/handlers/auth_test.go b/handlers/auth_test.go index 5b2688c..8512d55 100644 --- a/handlers/auth_test.go +++ b/handlers/auth_test.go @@ -70,7 +70,7 @@ func TestSign(t *testing.T) { Key: pubKeyHex, } - _, err = prepareBearerToken(bt, false) + _, err = prepareBearerToken(bt, false, false) require.NoError(t, err) } diff --git a/handlers/containers.go b/handlers/containers.go index c0d1d25..f08ce3f 100644 --- a/handlers/containers.go +++ b/handlers/containers.go @@ -37,14 +37,12 @@ const ( // PutContainers handler that creates container in NeoFS. func (a *API) PutContainers(params operations.PutContainerParams, principal *models.Principal) middleware.Responder { - st := &SessionToken{ - BearerToken: BearerToken{ - Token: string(*principal), - Signature: params.XBearerSignature, - Key: params.XBearerSignatureKey, - }, - Verb: sessionv2.ContainerVerbPut, + st, err := formSessionTokenFromHeaders(principal, params.XBearerSignature, params.XBearerSignatureKey, sessionv2.ContainerVerbPut) + if err != nil { + resp := a.logAndGetErrorResponse("invalid session token headers", err) + return operations.NewPutContainerBadRequest().WithPayload(resp) } + stoken, err := prepareSessionToken(st, *params.WalletConnect) if err != nil { resp := a.logAndGetErrorResponse("invalid session token", err) @@ -92,14 +90,12 @@ func (a *API) PutContainerEACL(params operations.PutContainerEACLParams, princip return operations.NewPutContainerEACLBadRequest().WithPayload(resp) } - st := &SessionToken{ - BearerToken: BearerToken{ - Token: string(*principal), - Signature: params.XBearerSignature, - Key: params.XBearerSignatureKey, - }, - Verb: sessionv2.ContainerVerbSetEACL, + st, err := formSessionTokenFromHeaders(principal, params.XBearerSignature, params.XBearerSignatureKey, sessionv2.ContainerVerbSetEACL) + if err != nil { + resp := a.logAndGetErrorResponse("invalid session token headers", err) + return operations.NewPutContainerEACLBadRequest().WithPayload(resp) } + stoken, err := prepareSessionToken(st, *params.WalletConnect) if err != nil { resp := a.logAndGetErrorResponse("invalid session token", err) @@ -192,14 +188,12 @@ func (a *API) ListContainer(params operations.ListContainersParams) middleware.R // DeleteContainer handler that returns container info. func (a *API) DeleteContainer(params operations.DeleteContainerParams, principal *models.Principal) middleware.Responder { - st := &SessionToken{ - BearerToken: BearerToken{ - Token: string(*principal), - Signature: params.XBearerSignature, - Key: params.XBearerSignatureKey, - }, - Verb: sessionv2.ContainerVerbDelete, + st, err := formSessionTokenFromHeaders(principal, params.XBearerSignature, params.XBearerSignatureKey, sessionv2.ContainerVerbDelete) + if err != nil { + resp := a.logAndGetErrorResponse("invalid session token headers", err) + return operations.NewDeleteContainerBadRequest().WithPayload(resp) } + stoken, err := prepareSessionToken(st, *params.WalletConnect) if err != nil { resp := a.logAndGetErrorResponse("invalid session token", err) diff --git a/handlers/objects.go b/handlers/objects.go index fae273c..f074089 100644 --- a/handlers/objects.go +++ b/handlers/objects.go @@ -33,7 +33,13 @@ func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Pr errorResponse := operations.NewPutObjectBadRequest() ctx := params.HTTPRequest.Context() - btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect) + bearerHeaders, err := prepareBearerTokenHeaders(params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect, *params.FullBearer) + if err != nil { + resp := a.logAndGetErrorResponse("invalid bearer headers", err) + return errorResponse.WithPayload(resp) + } + + btoken, err := getBearerToken(principal, bearerHeaders) if err != nil { resp := a.logAndGetErrorResponse("invalid bearer token", err) return errorResponse.WithPayload(resp) @@ -99,7 +105,13 @@ func (a *API) GetObjectInfo(params operations.GetObjectInfoParams, principal *mo return errorResponse.WithPayload(resp) } - btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect) + bearerHeaders, err := prepareBearerTokenHeaders(params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect, *params.FullBearer) + if err != nil { + resp := a.logAndGetErrorResponse("invalid bearer headers", err) + return errorResponse.WithPayload(resp) + } + + btoken, err := getBearerToken(principal, bearerHeaders) if err != nil { resp := a.logAndGetErrorResponse("get bearer token", err) return errorResponse.WithPayload(resp) @@ -195,7 +207,13 @@ func (a *API) DeleteObject(params operations.DeleteObjectParams, principal *mode return errorResponse.WithPayload(resp) } - btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect) + bearerHeaders, err := prepareBearerTokenHeaders(params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect, *params.FullBearer) + if err != nil { + resp := a.logAndGetErrorResponse("invalid bearer headers", err) + return errorResponse.WithPayload(resp) + } + + btoken, err := getBearerToken(principal, bearerHeaders) if err != nil { resp := a.logAndGetErrorResponse("failed to get bearer token", err) return errorResponse.WithPayload(resp) @@ -226,7 +244,13 @@ func (a *API) SearchObjects(params operations.SearchObjectsParams, principal *mo return errorResponse.WithPayload(resp) } - btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect) + bearerHeaders, err := prepareBearerTokenHeaders(params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect, *params.FullBearer) + if err != nil { + resp := a.logAndGetErrorResponse("invalid bearer headers", err) + return errorResponse.WithPayload(resp) + } + + btoken, err := getBearerToken(principal, bearerHeaders) if err != nil { resp := a.logAndGetErrorResponse("failed to get bearer token", err) return errorResponse.WithPayload(resp) @@ -339,22 +363,41 @@ func parseAddress(containerID, objectID string) (oid.Address, error) { return addr, nil } -func getBearerToken(token *models.Principal, signature, key string, isWalletConnect bool) (bearer.Token, error) { - bt := &BearerToken{ - Token: string(*token), - Signature: signature, - Key: key, - } - - return prepareBearerToken(bt, isWalletConnect) +type BearerTokenHeaders struct { + Signature string + Key string + IsWalletConnect bool + IsFullToken bool } -func prepareBearerToken(bt *BearerToken, isWalletConnect bool) (bearer.Token, error) { +func getBearerToken(token *models.Principal, hdr *BearerTokenHeaders) (bearer.Token, error) { + bt := &BearerToken{ + Token: string(*token), + Signature: hdr.Signature, + Key: hdr.Key, + } + + return prepareBearerToken(bt, hdr.IsWalletConnect, hdr.IsFullToken) +} + +func prepareBearerToken(bt *BearerToken, isWalletConnect, isFullToken bool) (bearer.Token, error) { data, err := base64.StdEncoding.DecodeString(bt.Token) if err != nil { return bearer.Token{}, fmt.Errorf("can't base64-decode bearer token: %w", err) } + if isFullToken { + var btoken bearer.Token + if err = btoken.Unmarshal(data); err != nil { + return bearer.Token{}, fmt.Errorf("couldn't unmarshall bearer token: %w", err) + } + if !btoken.VerifySignature() { + return bearer.Token{}, fmt.Errorf("invalid signature") + } + + return btoken, nil + } + signature, err := hex.DecodeString(bt.Signature) if err != nil { return bearer.Token{}, fmt.Errorf("couldn't decode bearer signature: %w", err) @@ -367,7 +410,7 @@ func prepareBearerToken(bt *BearerToken, isWalletConnect bool) (bearer.Token, er body := new(acl.BearerTokenBody) if err = body.Unmarshal(data); err != nil { - return bearer.Token{}, fmt.Errorf("can't unmarshal bearer token: %w", err) + return bearer.Token{}, fmt.Errorf("can't unmarshal bearer token body: %w", err) } v2signature := new(refs.Signature) diff --git a/handlers/util.go b/handlers/util.go index 2233249..c708014 100644 --- a/handlers/util.go +++ b/handlers/util.go @@ -2,11 +2,13 @@ package handlers import ( "context" + "errors" "fmt" "strconv" "time" objectv2 "github.com/nspcc-dev/neofs-api-go/v2/object" + sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-rest-gw/gen/models" "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/pool" @@ -171,3 +173,37 @@ func IsObjectToken(token *models.Bearer) (bool, error) { return isObject, nil } + +func prepareBearerTokenHeaders(signature, key *string, isWalletConnect, isFullToken bool) (*BearerTokenHeaders, error) { + bearerHeaders := &BearerTokenHeaders{ + IsWalletConnect: isWalletConnect, + IsFullToken: isFullToken, + } + if isFullToken { + return bearerHeaders, nil + } + + if signature == nil || key == nil { + return nil, errors.New("missed signature or key header") + } + + bearerHeaders.Signature = *signature + bearerHeaders.Key = *key + + return bearerHeaders, nil +} + +func formSessionTokenFromHeaders(principal *models.Principal, signature, key *string, verb sessionv2.ContainerSessionVerb) (*SessionToken, error) { + if signature == nil || key == nil { + return nil, errors.New("missed signature or key header") + } + + return &SessionToken{ + BearerToken: BearerToken{ + Token: string(*principal), + Signature: *signature, + Key: *key, + }, + Verb: verb, + }, nil +} diff --git a/spec/rest.yaml b/spec/rest.yaml index ac03699..5bc7bda 100644 --- a/spec/rest.yaml +++ b/spec/rest.yaml @@ -25,19 +25,25 @@ parameters: name: X-Bearer-Signature description: Base64 encoded signature for bearer token. type: string - required: true + required: false signatureKeyParam: in: header name: X-Bearer-Signature-Key description: Hex encoded the public part of the key that signed the bearer token. type: string - required: true + required: false signatureScheme: in: query name: walletConnect description: Use wallet connect signature scheme or native NeoFS signature. type: boolean default: false + fullBearerToken: + in: query + name: fullBearer + description: Provided bearer token is final or gate should assemble it using signature. + type: boolean + default: false containerId: in: path name: containerId @@ -182,6 +188,7 @@ paths: - $ref: '#/parameters/signatureParam' - $ref: '#/parameters/signatureKeyParam' - $ref: '#/parameters/signatureScheme' + - $ref: '#/parameters/fullBearerToken' - in: body required: true name: object @@ -226,6 +233,7 @@ paths: - $ref: '#/parameters/signatureParam' - $ref: '#/parameters/signatureKeyParam' - $ref: '#/parameters/signatureScheme' + - $ref: '#/parameters/fullBearerToken' - in: query name: offset type: integer @@ -282,6 +290,7 @@ paths: - $ref: '#/parameters/signatureParam' - $ref: '#/parameters/signatureKeyParam' - $ref: '#/parameters/signatureScheme' + - $ref: '#/parameters/fullBearerToken' - in: query name: range-offset type: integer @@ -320,6 +329,7 @@ paths: - $ref: '#/parameters/signatureParam' - $ref: '#/parameters/signatureKeyParam' - $ref: '#/parameters/signatureScheme' + - $ref: '#/parameters/fullBearerToken' responses: 200: headers: