forked from TrueCloudLab/frostfs-rest-gw
[#36] Add route to put storage group
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
ba464ddfa3
commit
e5b9fd5f5a
10 changed files with 950 additions and 0 deletions
130
gen/models/storage_group.go
Normal file
130
gen/models/storage_group.go
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StorageGroup Storage group keeps verification information for Data Audit sessions.
|
||||||
|
//
|
||||||
|
// swagger:model StorageGroup
|
||||||
|
type StorageGroup struct {
|
||||||
|
|
||||||
|
// Container id to which storage group is belong. Set by server.
|
||||||
|
// Read Only: true
|
||||||
|
ContainerID string `json:"containerId,omitempty"`
|
||||||
|
|
||||||
|
// Lifetime in epochs for storage group.
|
||||||
|
// Required: true
|
||||||
|
Lifetime *int64 `json:"lifetime"`
|
||||||
|
|
||||||
|
// Object identifiers to be placed into storage group. Must be unique.
|
||||||
|
// Required: true
|
||||||
|
Members []string `json:"members"`
|
||||||
|
|
||||||
|
// Name of storage group. It will be the value of the `FileName` attribute in storage group object.
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
|
// Object id of storage group. Set by server.
|
||||||
|
// Read Only: true
|
||||||
|
ObjectID string `json:"objectId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates this storage group
|
||||||
|
func (m *StorageGroup) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateLifetime(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.validateMembers(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StorageGroup) validateLifetime(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("lifetime", "body", m.Lifetime); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StorageGroup) validateMembers(formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.Required("members", "body", m.Members); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextValidate validate this storage group based on the context it is used
|
||||||
|
func (m *StorageGroup) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.contextValidateContainerID(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.contextValidateObjectID(ctx, formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StorageGroup) contextValidateContainerID(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.ReadOnly(ctx, "containerId", "body", string(m.ContainerID)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StorageGroup) contextValidateObjectID(ctx context.Context, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
if err := validate.ReadOnly(ctx, "objectId", "body", string(m.ObjectID)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary interface implementation
|
||||||
|
func (m *StorageGroup) MarshalBinary() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return swag.WriteJSON(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary interface implementation
|
||||||
|
func (m *StorageGroup) UnmarshalBinary(b []byte) error {
|
||||||
|
var res StorageGroup
|
||||||
|
if err := swag.ReadJSON(b, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = res
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -523,6 +523,51 @@ func init() {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"/containers/{containerId}/storagegroups": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Create a new storage group in container.",
|
||||||
|
"operationId": "putStorageGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureParam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureKeyParam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/signatureScheme"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Storage group co create.",
|
||||||
|
"name": "storageGroup",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/StorageGroup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Address of uploaded storage group.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/parameters/containerId"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"/objects": {
|
"/objects": {
|
||||||
"put": {
|
"put": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
|
@ -1522,6 +1567,41 @@ func init() {
|
||||||
"MatchCommonPrefix"
|
"MatchCommonPrefix"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"StorageGroup": {
|
||||||
|
"description": "Storage group keeps verification information for Data Audit sessions.",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"lifetime",
|
||||||
|
"members"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"containerId": {
|
||||||
|
"description": "Container id to which storage group is belong. Set by server.",
|
||||||
|
"type": "string",
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"lifetime": {
|
||||||
|
"description": "Lifetime in epochs for storage group.",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"description": "Object identifiers to be placed into storage group. Must be unique.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of storage group. It will be the value of the ` + "`" + `FileName` + "`" + ` attribute in storage group object.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"objectId": {
|
||||||
|
"description": "Object id of storage group. Set by server.",
|
||||||
|
"type": "string",
|
||||||
|
"readOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"SuccessResponse": {
|
"SuccessResponse": {
|
||||||
"description": "Success response.",
|
"description": "Success response.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -2220,6 +2300,67 @@ func init() {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"/containers/{containerId}/storagegroups": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Create a new storage group in container.",
|
||||||
|
"operationId": "putStorageGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Base64 encoded signature for bearer token.",
|
||||||
|
"name": "X-Bearer-Signature",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Hex encoded the public part of the key that signed the bearer token.",
|
||||||
|
"name": "X-Bearer-Signature-Key",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Use wallet connect signature scheme or native NeoFS signature.",
|
||||||
|
"name": "walletConnect",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Storage group co create.",
|
||||||
|
"name": "storageGroup",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/StorageGroup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Address of uploaded storage group.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Base58 encoded container id.",
|
||||||
|
"name": "containerId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"/objects": {
|
"/objects": {
|
||||||
"put": {
|
"put": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
|
@ -3290,6 +3431,41 @@ func init() {
|
||||||
"MatchCommonPrefix"
|
"MatchCommonPrefix"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"StorageGroup": {
|
||||||
|
"description": "Storage group keeps verification information for Data Audit sessions.",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"lifetime",
|
||||||
|
"members"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"containerId": {
|
||||||
|
"description": "Container id to which storage group is belong. Set by server.",
|
||||||
|
"type": "string",
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"lifetime": {
|
||||||
|
"description": "Lifetime in epochs for storage group.",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"description": "Object identifiers to be placed into storage group. Must be unique.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of storage group. It will be the value of the ` + "`" + `FileName` + "`" + ` attribute in storage group object.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"objectId": {
|
||||||
|
"description": "Object id of storage group. Set by server.",
|
||||||
|
"type": "string",
|
||||||
|
"readOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"SuccessResponse": {
|
"SuccessResponse": {
|
||||||
"description": "Success response.",
|
"description": "Success response.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
@ -104,6 +104,9 @@ func NewFrostfsRestGwAPI(spec *loads.Document) *FrostfsRestGwAPI {
|
||||||
PutObjectHandler: PutObjectHandlerFunc(func(params PutObjectParams, principal *models.Principal) middleware.Responder {
|
PutObjectHandler: PutObjectHandlerFunc(func(params PutObjectParams, principal *models.Principal) middleware.Responder {
|
||||||
return middleware.NotImplemented("operation PutObject has not yet been implemented")
|
return middleware.NotImplemented("operation PutObject has not yet been implemented")
|
||||||
}),
|
}),
|
||||||
|
PutStorageGroupHandler: PutStorageGroupHandlerFunc(func(params PutStorageGroupParams, principal *models.Principal) middleware.Responder {
|
||||||
|
return middleware.NotImplemented("operation PutStorageGroup has not yet been implemented")
|
||||||
|
}),
|
||||||
SearchObjectsHandler: SearchObjectsHandlerFunc(func(params SearchObjectsParams, principal *models.Principal) middleware.Responder {
|
SearchObjectsHandler: SearchObjectsHandlerFunc(func(params SearchObjectsParams, principal *models.Principal) middleware.Responder {
|
||||||
return middleware.NotImplemented("operation SearchObjects has not yet been implemented")
|
return middleware.NotImplemented("operation SearchObjects has not yet been implemented")
|
||||||
}),
|
}),
|
||||||
|
@ -197,6 +200,8 @@ type FrostfsRestGwAPI struct {
|
||||||
PutContainerEACLHandler PutContainerEACLHandler
|
PutContainerEACLHandler PutContainerEACLHandler
|
||||||
// PutObjectHandler sets the operation handler for the put object operation
|
// PutObjectHandler sets the operation handler for the put object operation
|
||||||
PutObjectHandler PutObjectHandler
|
PutObjectHandler PutObjectHandler
|
||||||
|
// PutStorageGroupHandler sets the operation handler for the put storage group operation
|
||||||
|
PutStorageGroupHandler PutStorageGroupHandler
|
||||||
// SearchObjectsHandler sets the operation handler for the search objects operation
|
// SearchObjectsHandler sets the operation handler for the search objects operation
|
||||||
SearchObjectsHandler SearchObjectsHandler
|
SearchObjectsHandler SearchObjectsHandler
|
||||||
|
|
||||||
|
@ -340,6 +345,9 @@ func (o *FrostfsRestGwAPI) Validate() error {
|
||||||
if o.PutObjectHandler == nil {
|
if o.PutObjectHandler == nil {
|
||||||
unregistered = append(unregistered, "PutObjectHandler")
|
unregistered = append(unregistered, "PutObjectHandler")
|
||||||
}
|
}
|
||||||
|
if o.PutStorageGroupHandler == nil {
|
||||||
|
unregistered = append(unregistered, "PutStorageGroupHandler")
|
||||||
|
}
|
||||||
if o.SearchObjectsHandler == nil {
|
if o.SearchObjectsHandler == nil {
|
||||||
unregistered = append(unregistered, "SearchObjectsHandler")
|
unregistered = append(unregistered, "SearchObjectsHandler")
|
||||||
}
|
}
|
||||||
|
@ -522,6 +530,10 @@ func (o *FrostfsRestGwAPI) initHandlerCache() {
|
||||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||||
}
|
}
|
||||||
o.handlers["PUT"]["/objects"] = NewPutObject(o.context, o.PutObjectHandler)
|
o.handlers["PUT"]["/objects"] = NewPutObject(o.context, o.PutObjectHandler)
|
||||||
|
if o.handlers["PUT"] == nil {
|
||||||
|
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||||
|
}
|
||||||
|
o.handlers["PUT"]["/containers/{containerId}/storagegroups"] = NewPutStorageGroup(o.context, o.PutStorageGroupHandler)
|
||||||
if o.handlers["POST"] == nil {
|
if o.handlers["POST"] == nil {
|
||||||
o.handlers["POST"] = make(map[string]http.Handler)
|
o.handlers["POST"] = make(map[string]http.Handler)
|
||||||
}
|
}
|
||||||
|
|
71
gen/restapi/operations/put_storage_group.go
Normal file
71
gen/restapi/operations/put_storage_group.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package operations
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-openapi/runtime/middleware"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PutStorageGroupHandlerFunc turns a function with the right signature into a put storage group handler
|
||||||
|
type PutStorageGroupHandlerFunc func(PutStorageGroupParams, *models.Principal) middleware.Responder
|
||||||
|
|
||||||
|
// Handle executing the request and returning a response
|
||||||
|
func (fn PutStorageGroupHandlerFunc) Handle(params PutStorageGroupParams, principal *models.Principal) middleware.Responder {
|
||||||
|
return fn(params, principal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutStorageGroupHandler interface for that can handle valid put storage group params
|
||||||
|
type PutStorageGroupHandler interface {
|
||||||
|
Handle(PutStorageGroupParams, *models.Principal) middleware.Responder
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutStorageGroup creates a new http.Handler for the put storage group operation
|
||||||
|
func NewPutStorageGroup(ctx *middleware.Context, handler PutStorageGroupHandler) *PutStorageGroup {
|
||||||
|
return &PutStorageGroup{Context: ctx, Handler: handler}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PutStorageGroup swagger:route PUT /containers/{containerId}/storagegroups putStorageGroup
|
||||||
|
|
||||||
|
Create a new storage group in container.
|
||||||
|
|
||||||
|
*/
|
||||||
|
type PutStorageGroup struct {
|
||||||
|
Context *middleware.Context
|
||||||
|
Handler PutStorageGroupHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutStorageGroup) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||||
|
if rCtx != nil {
|
||||||
|
*r = *rCtx
|
||||||
|
}
|
||||||
|
var Params = NewPutStorageGroupParams()
|
||||||
|
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)
|
||||||
|
|
||||||
|
}
|
212
gen/restapi/operations/put_storage_group_parameters.go
Normal file
212
gen/restapi/operations/put_storage_group_parameters.go
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
package operations
|
||||||
|
|
||||||
|
// This file was generated by the swagger tool.
|
||||||
|
// Editing this file might prove futile when you re-run the swagger generate command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
"github.com/go-openapi/runtime/middleware"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPutStorageGroupParams creates a new PutStorageGroupParams object
|
||||||
|
// with the default values initialized.
|
||||||
|
func NewPutStorageGroupParams() PutStorageGroupParams {
|
||||||
|
|
||||||
|
var (
|
||||||
|
// initialize parameters with default values
|
||||||
|
|
||||||
|
walletConnectDefault = bool(false)
|
||||||
|
)
|
||||||
|
|
||||||
|
return PutStorageGroupParams{
|
||||||
|
WalletConnect: &walletConnectDefault,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutStorageGroupParams contains all the bound params for the put storage group operation
|
||||||
|
// typically these are obtained from a http.Request
|
||||||
|
//
|
||||||
|
// swagger:parameters putStorageGroup
|
||||||
|
type PutStorageGroupParams 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
|
||||||
|
/*Storage group co create.
|
||||||
|
Required: true
|
||||||
|
In: body
|
||||||
|
*/
|
||||||
|
StorageGroup *models.StorageGroup
|
||||||
|
/*Use wallet connect signature scheme or native NeoFS signature.
|
||||||
|
In: query
|
||||||
|
Default: false
|
||||||
|
*/
|
||||||
|
WalletConnect *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||||
|
// for simple values it will use straight method calls.
|
||||||
|
//
|
||||||
|
// To ensure default values, the struct must have been initialized with NewPutStorageGroupParams() beforehand.
|
||||||
|
func (o *PutStorageGroupParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
o.HTTPRequest = r
|
||||||
|
|
||||||
|
qs := runtime.Values(r.URL.Query())
|
||||||
|
|
||||||
|
if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature")], true, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rContainerID, rhkContainerID, _ := route.Params.GetOK("containerId")
|
||||||
|
if err := o.bindContainerID(rContainerID, rhkContainerID, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.HasBody(r) {
|
||||||
|
defer r.Body.Close()
|
||||||
|
var body models.StorageGroup
|
||||||
|
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
res = append(res, errors.Required("storageGroup", "body", ""))
|
||||||
|
} else {
|
||||||
|
res = append(res, errors.NewParseError("storageGroup", "body", "", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// validate body object
|
||||||
|
if err := body.Validate(route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := validate.WithOperationRequest(context.Background())
|
||||||
|
if err := body.ContextValidate(ctx, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) == 0 {
|
||||||
|
o.StorageGroup = &body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = append(res, errors.Required("storageGroup", "body", ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
qWalletConnect, qhkWalletConnect, _ := qs.GetOK("walletConnect")
|
||||||
|
if err := o.bindWalletConnect(qWalletConnect, qhkWalletConnect, route.Formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindXBearerSignature binds and validates parameter XBearerSignature from header.
|
||||||
|
func (o *PutStorageGroupParams) 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 *PutStorageGroupParams) 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 *PutStorageGroupParams) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindWalletConnect binds and validates parameter WalletConnect from query.
|
||||||
|
func (o *PutStorageGroupParams) bindWalletConnect(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: false
|
||||||
|
// AllowEmptyValue: false
|
||||||
|
|
||||||
|
if raw == "" { // empty values pass all other validations
|
||||||
|
// Default values have been previously initialized by NewPutStorageGroupParams()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := swag.ConvertBool(raw)
|
||||||
|
if err != nil {
|
||||||
|
return errors.InvalidType("walletConnect", "query", "bool", raw)
|
||||||
|
}
|
||||||
|
o.WalletConnect = &value
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
102
gen/restapi/operations/put_storage_group_responses.go
Normal file
102
gen/restapi/operations/put_storage_group_responses.go
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PutStorageGroupOKCode is the HTTP code returned for type PutStorageGroupOK
|
||||||
|
const PutStorageGroupOKCode int = 200
|
||||||
|
|
||||||
|
/*PutStorageGroupOK Address of uploaded storage group.
|
||||||
|
|
||||||
|
swagger:response putStorageGroupOK
|
||||||
|
*/
|
||||||
|
type PutStorageGroupOK struct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
In: Body
|
||||||
|
*/
|
||||||
|
Payload *models.Address `json:"body,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutStorageGroupOK creates PutStorageGroupOK with default headers values
|
||||||
|
func NewPutStorageGroupOK() *PutStorageGroupOK {
|
||||||
|
|
||||||
|
return &PutStorageGroupOK{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPayload adds the payload to the put storage group o k response
|
||||||
|
func (o *PutStorageGroupOK) WithPayload(payload *models.Address) *PutStorageGroupOK {
|
||||||
|
o.Payload = payload
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayload sets the payload to the put storage group o k response
|
||||||
|
func (o *PutStorageGroupOK) SetPayload(payload *models.Address) {
|
||||||
|
o.Payload = payload
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteResponse to the client
|
||||||
|
func (o *PutStorageGroupOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||||
|
|
||||||
|
rw.WriteHeader(200)
|
||||||
|
if o.Payload != nil {
|
||||||
|
payload := o.Payload
|
||||||
|
if err := producer.Produce(rw, payload); err != nil {
|
||||||
|
panic(err) // let the recovery middleware deal with this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutStorageGroupBadRequestCode is the HTTP code returned for type PutStorageGroupBadRequest
|
||||||
|
const PutStorageGroupBadRequestCode int = 400
|
||||||
|
|
||||||
|
/*PutStorageGroupBadRequest Bad request.
|
||||||
|
|
||||||
|
swagger:response putStorageGroupBadRequest
|
||||||
|
*/
|
||||||
|
type PutStorageGroupBadRequest struct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
In: Body
|
||||||
|
*/
|
||||||
|
Payload *models.ErrorResponse `json:"body,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutStorageGroupBadRequest creates PutStorageGroupBadRequest with default headers values
|
||||||
|
func NewPutStorageGroupBadRequest() *PutStorageGroupBadRequest {
|
||||||
|
|
||||||
|
return &PutStorageGroupBadRequest{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPayload adds the payload to the put storage group bad request response
|
||||||
|
func (o *PutStorageGroupBadRequest) WithPayload(payload *models.ErrorResponse) *PutStorageGroupBadRequest {
|
||||||
|
o.Payload = payload
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPayload sets the payload to the put storage group bad request response
|
||||||
|
func (o *PutStorageGroupBadRequest) SetPayload(payload *models.ErrorResponse) {
|
||||||
|
o.Payload = payload
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteResponse to the client
|
||||||
|
func (o *PutStorageGroupBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||||
|
|
||||||
|
rw.WriteHeader(400)
|
||||||
|
if o.Payload != nil {
|
||||||
|
payload := o.Payload
|
||||||
|
if err := producer.Produce(rw, payload); err != nil {
|
||||||
|
panic(err) // let the recovery middleware deal with this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,6 +126,8 @@ func (a *API) Configure(api *operations.FrostfsRestGwAPI) http.Handler {
|
||||||
api.OptionsContainersEACLHandler = operations.OptionsContainersEACLHandlerFunc(a.OptionsContainersEACL)
|
api.OptionsContainersEACLHandler = operations.OptionsContainersEACLHandlerFunc(a.OptionsContainersEACL)
|
||||||
api.PutContainerEACLHandler = operations.PutContainerEACLHandlerFunc(a.PutContainerEACL)
|
api.PutContainerEACLHandler = operations.PutContainerEACLHandlerFunc(a.PutContainerEACL)
|
||||||
api.GetContainerEACLHandler = operations.GetContainerEACLHandlerFunc(a.GetContainerEACL)
|
api.GetContainerEACLHandler = operations.GetContainerEACLHandlerFunc(a.GetContainerEACL)
|
||||||
|
api.ListContainersHandler = operations.ListContainersHandlerFunc(a.ListContainer)
|
||||||
|
api.PutStorageGroupHandler = operations.PutStorageGroupHandlerFunc(a.PutStorageGroup)
|
||||||
|
|
||||||
api.BearerAuthAuth = func(s string) (*models.Principal, error) {
|
api.BearerAuthAuth = func(s string) (*models.Principal, error) {
|
||||||
if !strings.HasPrefix(s, BearerPrefix) {
|
if !strings.HasPrefix(s, BearerPrefix) {
|
||||||
|
|
|
@ -413,6 +413,10 @@ func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container
|
||||||
container.WriteDomain(&cnr, domain)
|
container.WriteDomain(&cnr, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = pool.SyncContainerWithNetwork(ctx, &cnr, p); err != nil {
|
||||||
|
return cid.ID{}, fmt.Errorf("sync container with network: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var prm pool.PrmContainerPut
|
var prm pool.PrmContainerPut
|
||||||
prm.SetContainer(cnr)
|
prm.SetContainer(cnr)
|
||||||
prm.WithinSession(stoken)
|
prm.WithinSession(stoken)
|
||||||
|
|
190
handlers/storagegroup.go
Normal file
190
handlers/storagegroup.go
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-openapi/runtime/middleware"
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations"
|
||||||
|
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
||||||
|
"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/object"
|
||||||
|
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/storagegroup"
|
||||||
|
"github.com/nspcc-dev/tzhash/tz"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PutStorageGroup handler that create a new storage group.
|
||||||
|
func (a *API) PutStorageGroup(params operations.PutStorageGroupParams, principal *models.Principal) middleware.Responder {
|
||||||
|
ctx := params.HTTPRequest.Context()
|
||||||
|
|
||||||
|
cnrID, err := parseContainerID(params.ContainerID)
|
||||||
|
if err != nil {
|
||||||
|
resp := a.logAndGetErrorResponse("invalid container id", err)
|
||||||
|
return operations.NewPutStorageGroupBadRequest().WithPayload(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect)
|
||||||
|
if err != nil {
|
||||||
|
resp := a.logAndGetErrorResponse("invalid bearer token", err)
|
||||||
|
return operations.NewPutStorageGroupBadRequest().WithPayload(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
sg, err := a.formStorageGroup(ctx, cnrID, btoken, params.StorageGroup)
|
||||||
|
if err != nil {
|
||||||
|
resp := a.logAndGetErrorResponse("form storage group", err)
|
||||||
|
return operations.NewPutStorageGroupBadRequest().WithPayload(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
objID, err := a.putStorageGroupObject(ctx, cnrID, btoken, params.StorageGroup.Name, *sg)
|
||||||
|
if err != nil {
|
||||||
|
resp := a.logAndGetErrorResponse("put storage group", err)
|
||||||
|
return operations.NewPutStorageGroupBadRequest().WithPayload(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp models.Address
|
||||||
|
resp.ContainerID = util.NewString(params.ContainerID)
|
||||||
|
resp.ObjectID = util.NewString(objID.String())
|
||||||
|
|
||||||
|
return operations.NewPutStorageGroupOK().WithPayload(&resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) formStorageGroup(ctx context.Context, cnrID cid.ID, btoken bearer.Token, storageGroup *models.StorageGroup) (*storagegroup.StorageGroup, error) {
|
||||||
|
members, err := a.parseStorageGroupMembers(storageGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parse storage group members: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
needCalcHash, err := isHomomorphicHashingDisabled(ctx, a.pool, cnrID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("check if homomorphic hash disabled: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sgSize, cs, err := a.getStorageGroupSizeAndHash(ctx, cnrID, btoken, members, needCalcHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get storage group size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
networkInfo, err := a.pool.NetworkInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get network info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sg storagegroup.StorageGroup
|
||||||
|
sg.SetMembers(members)
|
||||||
|
sg.SetValidationDataSize(sgSize)
|
||||||
|
sg.SetExpirationEpoch(networkInfo.CurrentEpoch() + uint64(*storageGroup.Lifetime))
|
||||||
|
|
||||||
|
if needCalcHash {
|
||||||
|
sg.SetValidationDataHash(*cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) putStorageGroupObject(ctx context.Context, cnrID cid.ID, btoken bearer.Token, fileName string, sg storagegroup.StorageGroup) (*oid.ID, error) {
|
||||||
|
owner := bearer.ResolveIssuer(btoken)
|
||||||
|
|
||||||
|
var attrFileName object.Attribute
|
||||||
|
attrFileName.SetKey(object.AttributeFileName)
|
||||||
|
attrFileName.SetValue(fileName)
|
||||||
|
|
||||||
|
obj := object.New()
|
||||||
|
obj.SetContainerID(cnrID)
|
||||||
|
obj.SetOwnerID(&owner)
|
||||||
|
obj.SetAttributes(attrFileName)
|
||||||
|
|
||||||
|
storagegroup.WriteToObject(sg, obj)
|
||||||
|
|
||||||
|
var prmPut pool.PrmObjectPut
|
||||||
|
prmPut.SetHeader(*obj)
|
||||||
|
prmPut.UseBearer(btoken)
|
||||||
|
|
||||||
|
objID, err := a.pool.PutObject(ctx, prmPut)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("put object: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return objID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) getStorageGroupSizeAndHash(ctx context.Context, cnrID cid.ID, btoken bearer.Token, members []oid.ID, needCalcHash bool) (uint64, *checksum.Checksum, error) {
|
||||||
|
var (
|
||||||
|
sgSize uint64
|
||||||
|
objHashes [][]byte
|
||||||
|
addr oid.Address
|
||||||
|
prm pool.PrmObjectHead
|
||||||
|
)
|
||||||
|
|
||||||
|
addr.SetContainer(cnrID)
|
||||||
|
prm.UseBearer(btoken)
|
||||||
|
|
||||||
|
for _, objID := range members {
|
||||||
|
addr.SetObject(objID)
|
||||||
|
prm.SetAddress(addr)
|
||||||
|
|
||||||
|
objInfo, err := a.pool.HeadObject(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("chead object from storage group members, id '%s': %w", objID.EncodeToString(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sgSize += objInfo.PayloadSize()
|
||||||
|
|
||||||
|
if needCalcHash {
|
||||||
|
cs, _ := objInfo.PayloadHomomorphicHash()
|
||||||
|
objHashes = append(objHashes, cs.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if needCalcHash {
|
||||||
|
sumHash, err := tz.Concat(objHashes)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("concat tz hashes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cs checksum.Checksum
|
||||||
|
tzHash := [64]byte{}
|
||||||
|
copy(tzHash[:], sumHash)
|
||||||
|
cs.SetTillichZemor(tzHash)
|
||||||
|
|
||||||
|
return sgSize, &cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return sgSize, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) parseStorageGroupMembers(storageGroup *models.StorageGroup) ([]oid.ID, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
members := make([]oid.ID, len(storageGroup.Members))
|
||||||
|
uniqueFilter := make(map[oid.ID]struct{}, len(members))
|
||||||
|
|
||||||
|
for i, objIDStr := range storageGroup.Members {
|
||||||
|
if err = members[i].DecodeString(objIDStr); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid object id '%s': %w", objIDStr, err)
|
||||||
|
}
|
||||||
|
if _, ok := uniqueFilter[members[i]]; ok {
|
||||||
|
return nil, fmt.Errorf("invalid storage group members: duplicate id '%s': %w", objIDStr, err)
|
||||||
|
}
|
||||||
|
uniqueFilter[members[i]] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return members, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isHomomorphicHashingDisabled(ctx context.Context, p *pool.Pool, cnrID cid.ID) (bool, error) {
|
||||||
|
var prm pool.PrmContainerGet
|
||||||
|
prm.SetContainerID(cnrID)
|
||||||
|
|
||||||
|
cnr, err := p.GetContainer(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("get container: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return container.IsHomomorphicHashingDisabled(*cnr), nil
|
||||||
|
}
|
|
@ -556,6 +556,31 @@ paths:
|
||||||
description: Bad request.
|
description: Bad request.
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/ErrorResponse'
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
/containers/{containerId}/storagegroups:
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/containerId'
|
||||||
|
put:
|
||||||
|
operationId: putStorageGroup
|
||||||
|
summary: Create a new storage group in container.
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/signatureParam'
|
||||||
|
- $ref: '#/parameters/signatureKeyParam'
|
||||||
|
- $ref: '#/parameters/signatureScheme'
|
||||||
|
- in: body
|
||||||
|
name: storageGroup
|
||||||
|
required: true
|
||||||
|
description: Storage group co create.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/StorageGroup'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Address of uploaded storage group.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Address'
|
||||||
|
400:
|
||||||
|
description: Bad request.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
|
||||||
definitions:
|
definitions:
|
||||||
BinaryBearer:
|
BinaryBearer:
|
||||||
|
@ -1030,6 +1055,32 @@ definitions:
|
||||||
value: myfile
|
value: myfile
|
||||||
targets:
|
targets:
|
||||||
- role: OTHERS
|
- role: OTHERS
|
||||||
|
StorageGroup:
|
||||||
|
description: Storage group keeps verification information for Data Audit sessions.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Name of storage group. It will be the value of the `FileName` attribute in storage group object.
|
||||||
|
type: string
|
||||||
|
containerId:
|
||||||
|
description: Container id to which storage group is belong. Set by server.
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
objectId:
|
||||||
|
description: Object id of storage group. Set by server.
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
lifetime:
|
||||||
|
description: Lifetime in epochs for storage group.
|
||||||
|
type: integer
|
||||||
|
members:
|
||||||
|
description: Object identifiers to be placed into storage group. Must be unique.
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lifetime
|
||||||
|
- members
|
||||||
Attribute:
|
Attribute:
|
||||||
description: Attribute is a pair of strings that can be attached to a container or an object.
|
description: Attribute is a pair of strings that can be attached to a container or an object.
|
||||||
type: object
|
type: object
|
||||||
|
|
Loading…
Reference in a new issue