diff --git a/models/object_legal_hold_status.go b/models/object_legal_hold_status.go new file mode 100644 index 000000000..e945537b0 --- /dev/null +++ b/models/object_legal_hold_status.go @@ -0,0 +1,80 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +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 ( + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// ObjectLegalHoldStatus object legal hold status +// +// swagger:model objectLegalHoldStatus +type ObjectLegalHoldStatus string + +const ( + + // ObjectLegalHoldStatusEnabled captures enum value "enabled" + ObjectLegalHoldStatusEnabled ObjectLegalHoldStatus = "enabled" + + // ObjectLegalHoldStatusDisabled captures enum value "disabled" + ObjectLegalHoldStatusDisabled ObjectLegalHoldStatus = "disabled" +) + +// for schema +var objectLegalHoldStatusEnum []interface{} + +func init() { + var res []ObjectLegalHoldStatus + if err := json.Unmarshal([]byte(`["enabled","disabled"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + objectLegalHoldStatusEnum = append(objectLegalHoldStatusEnum, v) + } +} + +func (m ObjectLegalHoldStatus) validateObjectLegalHoldStatusEnum(path, location string, value ObjectLegalHoldStatus) error { + if err := validate.EnumCase(path, location, value, objectLegalHoldStatusEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this object legal hold status +func (m ObjectLegalHoldStatus) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateObjectLegalHoldStatusEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/models/put_object_legal_hold_request.go b/models/put_object_legal_hold_request.go new file mode 100644 index 000000000..1e65aa9fa --- /dev/null +++ b/models/put_object_legal_hold_request.go @@ -0,0 +1,83 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +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 ( + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// PutObjectLegalHoldRequest put object legal hold request +// +// swagger:model putObjectLegalHoldRequest +type PutObjectLegalHoldRequest struct { + + // status + // Required: true + Status ObjectLegalHoldStatus `json:"status"` +} + +// Validate validates this put object legal hold request +func (m *PutObjectLegalHoldRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateStatus(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *PutObjectLegalHoldRequest) validateStatus(formats strfmt.Registry) error { + + if err := m.Status.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("status") + } + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *PutObjectLegalHoldRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *PutObjectLegalHoldRequest) UnmarshalBinary(b []byte) error { + var res PutObjectLegalHoldRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/restapi/client.go b/restapi/client.go index 26110bcc4..2125670b6 100644 --- a/restapi/client.go +++ b/restapi/client.go @@ -59,6 +59,7 @@ type MinioClient interface { getObjectRetention(ctx context.Context, bucketName, objectName, versionID string) (mode *minio.RetentionMode, retainUntilDate *time.Time, err error) getObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.GetObjectLegalHoldOptions) (status *minio.LegalHoldStatus, err error) putObject(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (info minio.UploadInfo, err error) + putObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error } // Interface implementation @@ -133,6 +134,10 @@ func (c minioClient) putObject(ctx context.Context, bucketName, objectName strin return c.client.PutObject(ctx, bucketName, objectName, reader, objectSize, opts) } +func (c minioClient) putObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error { + return c.client.PutObjectLegalHold(ctx, bucketName, objectName, opts) +} + // MCClient interface with all functions to be implemented // by mock when testing, it should include all mc/S3Client respective api calls // that are used within this project. diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index f1e4fe3a0..20b27ed56 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -469,6 +469,54 @@ func init() { } } }, + "/buckets/{bucket_name}/objects/legalhold": { + "put": { + "tags": [ + "UserAPI" + ], + "summary": "Put Object's legalhold status", + "operationId": "PutObjectLegalHold", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + }, + { + "type": "string", + "name": "prefix", + "in": "query", + "required": true + }, + { + "type": "string", + "name": "version_id", + "in": "query", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/putObjectLegalHoldRequest" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/buckets/{bucket_name}/objects/share": { "get": { "tags": [ @@ -3695,6 +3743,13 @@ func init() { "get" ] }, + "objectLegalHoldStatus": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ] + }, "parityResponse": { "type": "array", "items": { @@ -3825,6 +3880,17 @@ func init() { } } }, + "putObjectLegalHoldRequest": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "$ref": "#/definitions/objectLegalHoldStatus" + } + } + }, "remoteBucket": { "type": "object", "required": [ @@ -5010,6 +5076,54 @@ func init() { } } }, + "/buckets/{bucket_name}/objects/legalhold": { + "put": { + "tags": [ + "UserAPI" + ], + "summary": "Put Object's legalhold status", + "operationId": "PutObjectLegalHold", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + }, + { + "type": "string", + "name": "prefix", + "in": "query", + "required": true + }, + { + "type": "string", + "name": "version_id", + "in": "query", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/putObjectLegalHoldRequest" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/buckets/{bucket_name}/objects/share": { "get": { "tags": [ @@ -8715,6 +8829,13 @@ func init() { "get" ] }, + "objectLegalHoldStatus": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ] + }, "parityResponse": { "type": "array", "items": { @@ -8823,6 +8944,17 @@ func init() { } } }, + "putObjectLegalHoldRequest": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "$ref": "#/definitions/objectLegalHoldStatus" + } + } + }, "remoteBucket": { "type": "object", "required": [ diff --git a/restapi/operations/console_api.go b/restapi/operations/console_api.go index dd424d091..274b46013 100644 --- a/restapi/operations/console_api.go +++ b/restapi/operations/console_api.go @@ -223,6 +223,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI { AdminAPIProfilingStopHandler: admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation admin_api.ProfilingStop has not yet been implemented") }), + UserAPIPutObjectLegalHoldHandler: user_api.PutObjectLegalHoldHandlerFunc(func(params user_api.PutObjectLegalHoldParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation user_api.PutObjectLegalHold has not yet been implemented") + }), UserAPIRemoteBucketDetailsHandler: user_api.RemoteBucketDetailsHandlerFunc(func(params user_api.RemoteBucketDetailsParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation user_api.RemoteBucketDetails has not yet been implemented") }), @@ -441,6 +444,8 @@ type ConsoleAPI struct { AdminAPIProfilingStartHandler admin_api.ProfilingStartHandler // AdminAPIProfilingStopHandler sets the operation handler for the profiling stop operation AdminAPIProfilingStopHandler admin_api.ProfilingStopHandler + // UserAPIPutObjectLegalHoldHandler sets the operation handler for the put object legal hold operation + UserAPIPutObjectLegalHoldHandler user_api.PutObjectLegalHoldHandler // UserAPIRemoteBucketDetailsHandler sets the operation handler for the remote bucket details operation UserAPIRemoteBucketDetailsHandler user_api.RemoteBucketDetailsHandler // AdminAPIRemoveGroupHandler sets the operation handler for the remove group operation @@ -716,6 +721,9 @@ func (o *ConsoleAPI) Validate() error { if o.AdminAPIProfilingStopHandler == nil { unregistered = append(unregistered, "admin_api.ProfilingStopHandler") } + if o.UserAPIPutObjectLegalHoldHandler == nil { + unregistered = append(unregistered, "user_api.PutObjectLegalHoldHandler") + } if o.UserAPIRemoteBucketDetailsHandler == nil { unregistered = append(unregistered, "user_api.RemoteBucketDetailsHandler") } @@ -1090,6 +1098,10 @@ func (o *ConsoleAPI) initHandlerCache() { o.handlers["POST"] = make(map[string]http.Handler) } o.handlers["POST"]["/profiling/stop"] = admin_api.NewProfilingStop(o.context, o.AdminAPIProfilingStopHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/buckets/{bucket_name}/objects/legalhold"] = user_api.NewPutObjectLegalHold(o.context, o.UserAPIPutObjectLegalHoldHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/restapi/operations/user_api/put_object_legal_hold.go b/restapi/operations/user_api/put_object_legal_hold.go new file mode 100644 index 000000000..d55c0a62b --- /dev/null +++ b/restapi/operations/user_api/put_object_legal_hold.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// 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/minio/console/models" +) + +// PutObjectLegalHoldHandlerFunc turns a function with the right signature into a put object legal hold handler +type PutObjectLegalHoldHandlerFunc func(PutObjectLegalHoldParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutObjectLegalHoldHandlerFunc) Handle(params PutObjectLegalHoldParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// PutObjectLegalHoldHandler interface for that can handle valid put object legal hold params +type PutObjectLegalHoldHandler interface { + Handle(PutObjectLegalHoldParams, *models.Principal) middleware.Responder +} + +// NewPutObjectLegalHold creates a new http.Handler for the put object legal hold operation +func NewPutObjectLegalHold(ctx *middleware.Context, handler PutObjectLegalHoldHandler) *PutObjectLegalHold { + return &PutObjectLegalHold{Context: ctx, Handler: handler} +} + +/*PutObjectLegalHold swagger:route PUT /buckets/{bucket_name}/objects/legalhold UserAPI putObjectLegalHold + +Put Object's legalhold status + +*/ +type PutObjectLegalHold struct { + Context *middleware.Context + Handler PutObjectLegalHoldHandler +} + +func (o *PutObjectLegalHold) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewPutObjectLegalHoldParams() + + 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/restapi/operations/user_api/put_object_legal_hold_parameters.go b/restapi/operations/user_api/put_object_legal_hold_parameters.go new file mode 100644 index 000000000..1c5b9a204 --- /dev/null +++ b/restapi/operations/user_api/put_object_legal_hold_parameters.go @@ -0,0 +1,185 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "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/validate" + + "github.com/minio/console/models" +) + +// NewPutObjectLegalHoldParams creates a new PutObjectLegalHoldParams object +// no default values defined in spec. +func NewPutObjectLegalHoldParams() PutObjectLegalHoldParams { + + return PutObjectLegalHoldParams{} +} + +// PutObjectLegalHoldParams contains all the bound params for the put object legal hold operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutObjectLegalHold +type PutObjectLegalHoldParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.PutObjectLegalHoldRequest + /* + Required: true + In: path + */ + BucketName string + /* + Required: true + In: query + */ + Prefix string + /* + Required: true + In: query + */ + VersionID 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 NewPutObjectLegalHoldParams() beforehand. +func (o *PutObjectLegalHoldParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.PutObjectLegalHoldRequest + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body", "")) + } else { + res = append(res, errors.NewParseError("body", "body", "", err)) + } + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body", "")) + } + rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name") + if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil { + res = append(res, err) + } + + qPrefix, qhkPrefix, _ := qs.GetOK("prefix") + if err := o.bindPrefix(qPrefix, qhkPrefix, route.Formats); err != nil { + res = append(res, err) + } + + qVersionID, qhkVersionID, _ := qs.GetOK("version_id") + if err := o.bindVersionID(qVersionID, qhkVersionID, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindBucketName binds and validates parameter BucketName from path. +func (o *PutObjectLegalHoldParams) bindBucketName(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.BucketName = raw + + return nil +} + +// bindPrefix binds and validates parameter Prefix from query. +func (o *PutObjectLegalHoldParams) bindPrefix(rawData []string, hasKey bool, formats strfmt.Registry) error { + if !hasKey { + return errors.Required("prefix", "query", rawData) + } + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // AllowEmptyValue: false + if err := validate.RequiredString("prefix", "query", raw); err != nil { + return err + } + + o.Prefix = raw + + return nil +} + +// bindVersionID binds and validates parameter VersionID from query. +func (o *PutObjectLegalHoldParams) bindVersionID(rawData []string, hasKey bool, formats strfmt.Registry) error { + if !hasKey { + return errors.Required("version_id", "query", rawData) + } + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // AllowEmptyValue: false + if err := validate.RequiredString("version_id", "query", raw); err != nil { + return err + } + + o.VersionID = raw + + return nil +} diff --git a/restapi/operations/user_api/put_object_legal_hold_responses.go b/restapi/operations/user_api/put_object_legal_hold_responses.go new file mode 100644 index 000000000..6a51191e7 --- /dev/null +++ b/restapi/operations/user_api/put_object_legal_hold_responses.go @@ -0,0 +1,113 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// 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/minio/console/models" +) + +// PutObjectLegalHoldOKCode is the HTTP code returned for type PutObjectLegalHoldOK +const PutObjectLegalHoldOKCode int = 200 + +/*PutObjectLegalHoldOK A successful response. + +swagger:response putObjectLegalHoldOK +*/ +type PutObjectLegalHoldOK struct { +} + +// NewPutObjectLegalHoldOK creates PutObjectLegalHoldOK with default headers values +func NewPutObjectLegalHoldOK() *PutObjectLegalHoldOK { + + return &PutObjectLegalHoldOK{} +} + +// WriteResponse to the client +func (o *PutObjectLegalHoldOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +/*PutObjectLegalHoldDefault Generic error response. + +swagger:response putObjectLegalHoldDefault +*/ +type PutObjectLegalHoldDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewPutObjectLegalHoldDefault creates PutObjectLegalHoldDefault with default headers values +func NewPutObjectLegalHoldDefault(code int) *PutObjectLegalHoldDefault { + if code <= 0 { + code = 500 + } + + return &PutObjectLegalHoldDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the put object legal hold default response +func (o *PutObjectLegalHoldDefault) WithStatusCode(code int) *PutObjectLegalHoldDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the put object legal hold default response +func (o *PutObjectLegalHoldDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the put object legal hold default response +func (o *PutObjectLegalHoldDefault) WithPayload(payload *models.Error) *PutObjectLegalHoldDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put object legal hold default response +func (o *PutObjectLegalHoldDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutObjectLegalHoldDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/user_api/put_object_legal_hold_urlbuilder.go b/restapi/operations/user_api/put_object_legal_hold_urlbuilder.go new file mode 100644 index 000000000..c4f6231df --- /dev/null +++ b/restapi/operations/user_api/put_object_legal_hold_urlbuilder.go @@ -0,0 +1,133 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutObjectLegalHoldURL generates an URL for the put object legal hold operation +type PutObjectLegalHoldURL struct { + BucketName string + + Prefix string + VersionID string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutObjectLegalHoldURL) WithBasePath(bp string) *PutObjectLegalHoldURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutObjectLegalHoldURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutObjectLegalHoldURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/buckets/{bucket_name}/objects/legalhold" + + bucketName := o.BucketName + if bucketName != "" { + _path = strings.Replace(_path, "{bucket_name}", bucketName, -1) + } else { + return nil, errors.New("bucketName is required on PutObjectLegalHoldURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + prefixQ := o.Prefix + if prefixQ != "" { + qs.Set("prefix", prefixQ) + } + + versionIDQ := o.VersionID + if versionIDQ != "" { + qs.Set("version_id", versionIDQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutObjectLegalHoldURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutObjectLegalHoldURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutObjectLegalHoldURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutObjectLegalHoldURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutObjectLegalHoldURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutObjectLegalHoldURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/user_objects.go b/restapi/user_objects.go index cfeaaf762..e8c44ebd0 100644 --- a/restapi/user_objects.go +++ b/restapi/user_objects.go @@ -92,6 +92,13 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) { } return user_api.NewShareObjectOK().WithPayload(*resp) }) + // set object legalhold status + api.UserAPIPutObjectLegalHoldHandler = user_api.PutObjectLegalHoldHandlerFunc(func(params user_api.PutObjectLegalHoldParams, session *models.Principal) middleware.Responder { + if err := getSetObjectLegalHoldResponse(session, params); err != nil { + return user_api.NewPutObjectLegalHoldDefault(int(err.Code)).WithPayload(err) + } + return user_api.NewPutObjectLegalHoldOK() + }) } // getListObjectsResponse returns a list of objects @@ -405,6 +412,33 @@ func getShareObjectURL(ctx context.Context, client MCClient, versionID string, d return &objURL, nil } +func getSetObjectLegalHoldResponse(session *models.Principal, params user_api.PutObjectLegalHoldParams) *models.Error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + mClient, err := newMinioClient(session) + if err != nil { + return prepareError(err) + } + // create a minioClient interface implementation + // defining the client to be used + minioClient := minioClient{client: mClient} + err = setObjectLegalHold(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID, params.Body.Status) + if err != nil { + return prepareError(err) + } + return nil +} + +func setObjectLegalHold(ctx context.Context, client MinioClient, bucketName, prefix, versionID string, status models.ObjectLegalHoldStatus) error { + var lstatus minio.LegalHoldStatus + if status == models.ObjectLegalHoldStatusEnabled { + lstatus = minio.LegalHoldEnabled + } else { + lstatus = minio.LegalHoldDisabled + } + return client.putObjectLegalHold(ctx, bucketName, prefix, minio.PutObjectLegalHoldOptions{VersionID: versionID, Status: &lstatus}) +} + // newClientURL returns an abstracted URL for filesystems and object storage. func newClientURL(urlStr string) *mc.ClientURL { scheme, rest := getScheme(urlStr) diff --git a/restapi/user_objects_test.go b/restapi/user_objects_test.go index bf1dc2204..682b18cef 100644 --- a/restapi/user_objects_test.go +++ b/restapi/user_objects_test.go @@ -35,7 +35,8 @@ import ( var minioListObjectsMock func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo var minioGetObjectLegalHoldMock func(ctx context.Context, bucketName, objectName string, opts minio.GetObjectLegalHoldOptions) (status *minio.LegalHoldStatus, err error) var minioGetObjectRetentionMock func(ctx context.Context, bucketName, objectName, versionID string) (mode *minio.RetentionMode, retainUntilDate *time.Time, err error) -var minioPutObject func(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (info minio.UploadInfo, err error) +var minioPutObjectMock func(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (info minio.UploadInfo, err error) +var minioPutObjectLegalHoldMock func(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error var mcListMock func(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent var mcRemoveMock func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan *probe.Error @@ -55,7 +56,11 @@ func (ac minioClientMock) getObjectRetention(ctx context.Context, bucketName, ob } func (ac minioClientMock) putObject(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (info minio.UploadInfo, err error) { - return minioPutObject(ctx, bucketName, objectName, reader, objectSize, opts) + return minioPutObjectMock(ctx, bucketName, objectName, reader, objectSize, opts) +} + +func (ac minioClientMock) putObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error { + return minioPutObjectLegalHoldMock(ctx, bucketName, objectName, opts) } // mock functions for s3ClientMock @@ -631,3 +636,71 @@ func Test_shareObject(t *testing.T) { }) } } + +func Test_putObjectLegalHold(t *testing.T) { + ctx := context.Background() + client := minioClientMock{} + type args struct { + bucket string + prefix string + versionID string + status models.ObjectLegalHoldStatus + legalHoldFunc func(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error + } + tests := []struct { + test string + args args + wantError error + }{ + { + test: "Put Object Legal hold enabled status", + args: args{ + bucket: "buck1", + versionID: "someversion", + prefix: "folder/file.txt", + status: models.ObjectLegalHoldStatusEnabled, + legalHoldFunc: func(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error { + return nil + }, + }, + wantError: nil, + }, + { + test: "Put Object Legal hold disabled status", + args: args{ + bucket: "buck1", + versionID: "someversion", + prefix: "folder/file.txt", + status: models.ObjectLegalHoldStatusDisabled, + legalHoldFunc: func(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error { + return nil + }, + }, + wantError: nil, + }, + { + test: "Handle error on legalhold func", + args: args{ + bucket: "buck1", + versionID: "someversion", + prefix: "folder/file.txt", + status: models.ObjectLegalHoldStatusDisabled, + legalHoldFunc: func(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error { + return errors.New("new error") + }, + }, + wantError: errors.New("new error"), + }, + } + + for _, tt := range tests { + t.Run(tt.test, func(t *testing.T) { + minioPutObjectLegalHoldMock = tt.args.legalHoldFunc + err := setObjectLegalHold(ctx, client, tt.args.bucket, tt.args.prefix, tt.args.versionID, tt.args.status) + if !reflect.DeepEqual(err, tt.wantError) { + t.Errorf("setObjectLegalHold() error: %v, wantErr: %v", err, tt.wantError) + return + } + }) + } +} diff --git a/swagger.yml b/swagger.yml index 4914220fc..e79a4fc51 100644 --- a/swagger.yml +++ b/swagger.yml @@ -373,6 +373,38 @@ paths: tags: - UserAPI + /buckets/{bucket_name}/objects/legalhold: + put: + summary: Put Object's legalhold status + operationId: PutObjectLegalHold + parameters: + - name: bucket_name + in: path + required: true + type: string + - name: prefix + in: query + required: true + type: string + - name: version_id + in: query + required: true + type: string + - name: body + in: body + required: true + schema: + $ref: "#/definitions/putObjectLegalHoldRequest" + responses: + 200: + description: A successful response. + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - UserAPI + /buckets/{name}/set-policy: put: summary: Bucket Set Policy @@ -3285,3 +3317,17 @@ definitions: type: array items: type: string + + objectLegalHoldStatus: + type: string + enum: + - enabled + - disabled + + putObjectLegalHoldRequest: + type: object + required: + - status + properties: + status: + $ref: "#/definitions/objectLegalHoldStatus"