Compare commits

...

4 Commits

Author SHA1 Message Date
Minio Trusted
fce361e5bd update to v0.4.3 2020-10-23 02:15:25 -07:00
Alex
ed6d6e8b9d Fixed audit issues (#342)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-10-23 02:03:49 -07:00
Alex
406709f66b Updated Watch view to have console consistent styles (#341)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-10-22 17:15:40 -07:00
Cesar N
3ac45a2211 Add Set object's legalhold status api (#339)
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-10-22 16:23:29 -07:00
21 changed files with 2142 additions and 2844 deletions

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa
containers:
- name: console
image: minio/console:v0.4.2
image: minio/console:v0.4.3
imagePullPolicy: "IfNotPresent"
args:
- server

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa
containers:
- name: console
image: minio/console:v0.4.2
image: minio/console:v0.4.3
imagePullPolicy: "IfNotPresent"
env:
- name: CONSOLE_OPERATOR_MODE

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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
}

File diff suppressed because one or more lines are too long

View File

@@ -28,7 +28,6 @@
"local-storage-fallback": "^4.1.1",
"lodash": "^4.17.19",
"moment": "^2.24.0",
"npm": "^6.14.4",
"react": "^16.13.1",
"react-app-rewire-hot-loader": "^2.0.1",
"react-app-rewired": "^2.1.6",
@@ -40,7 +39,7 @@
"react-moment": "^0.9.7",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-scripts": "3.4.4",
"recharts": "^1.8.5",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0",

View File

@@ -145,6 +145,7 @@ export const actionsTray = {
export const searchField = {
searchField: {
flexGrow: 1,
height: 40,
background: "#FFFFFF",
borderRadius: 5,
border: "#EAEDEE 1px solid",

View File

@@ -14,7 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react";
import { Button, Grid, Typography, TextField } from "@material-ui/core";
import {
Button,
Grid,
Typography,
TextField,
InputBase,
} from "@material-ui/core";
import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
import { AppState } from "../../../store";
import { connect } from "react-redux";
@@ -25,8 +31,17 @@ import { niceBytes, timeFromDate } from "../../../common/utils";
import { wsProtocol } from "../../../utils/wsUtils";
import api from "../../../common/api";
import { FormControl, MenuItem, Select } from "@material-ui/core";
import { containerForHeader } from "../Common/FormComponents/common/styleLibrary";
import {
actionsTray,
containerForHeader,
fieldBasic,
searchField,
} from "../Common/FormComponents/common/styleLibrary";
import PageHeader from "../Common/PageHeader/PageHeader";
import InputAdornment from "@material-ui/core/InputAdornment";
import SearchIcon from "@material-ui/icons/Search";
import { CreateIcon } from "../../../icons";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
const styles = (theme: Theme) =>
createStyles({
@@ -45,31 +60,34 @@ const styles = (theme: Theme) =>
borderBottom: "1px solid #dedede",
},
},
actionsTray: {
textAlign: "right",
"& button": {
marginLeft: 10,
},
},
inputField: {
background: "#FFFFFF",
padding: 12,
borderRadius: 5,
marginLeft: 10,
boxShadow: "0px 3px 6px #00000012",
},
fieldContainer: {
background: "#FFFFFF",
padding: 0,
borderRadius: 5,
marginLeft: 10,
textAlign: "left",
minWidth: "206px",
boxShadow: "0px 3px 6px #00000012",
searchPrefix: {
flexGrow: 1,
marginLeft: 15,
},
...actionsTray,
...searchField,
...containerForHeader(theme.spacing(4)),
});
const SelectStyled = withStyles((theme: Theme) =>
createStyles({
root: {
width: 450,
lineHeight: 1,
"label + &": {
marginTop: theme.spacing(3),
},
"& .MuiSelect-select:focus": {
backgroundColor: "transparent",
},
},
input: {
fontSize: 13,
lineHeight: 15,
},
})
)(InputBase);
interface IWatch {
classes: any;
watchMessageReceived: typeof watchMessageReceived;
@@ -156,6 +174,7 @@ const Watch = ({
label: bucketName.name,
value: bucketName.name,
}));
return (
<React.Fragment>
<PageHeader label="Watch" />
@@ -170,8 +189,9 @@ const Watch = ({
onChange={(e) => {
setBucketName(e.target.value as string);
}}
className={classes.fieldContainer}
className={classes.searchField}
disabled={start}
input={<SelectStyled />}
>
<MenuItem
value={bucketName}
@@ -192,7 +212,7 @@ const Watch = ({
</FormControl>
<TextField
placeholder="Prefix"
className={classes.inputField}
className={`${classes.searchField} ${classes.searchPrefix}`}
id="prefix-resource"
label=""
disabled={start}
@@ -205,7 +225,7 @@ const Watch = ({
/>
<TextField
placeholder="Suffix"
className={classes.inputField}
className={`${classes.searchField} ${classes.searchPrefix}`}
id="suffix-resource"
label=""
disabled={start}
@@ -229,18 +249,27 @@ const Watch = ({
<Grid item xs={12}>
<br />
</Grid>
<div className={classes.watchList}>
<ul>
{messages.map((m) => {
return (
<li key={m.key}>
{timeFromDate(m.Time)} - {niceBytes(m.Size + "")} - {m.Type}{" "}
- {m.Path}
</li>
);
})}
</ul>
</div>
<TableWrapper
columns={[
{
label: "Time",
elementKey: "Time",
renderFunction: timeFromDate,
},
{
label: "Size",
elementKey: "Size",
renderFunction: niceBytes,
},
{ label: "Type", elementKey: "Type" },
{ label: "Path", elementKey: "Path" },
]}
records={messages}
entityName={"Watch"}
customEmptyMessage={"No Changes at this time"}
idField={"watch_table"}
isLoading={false}
/>
</Grid>
</Grid>
</React.Fragment>

File diff suppressed because it is too large Load Diff

View File

@@ -679,7 +679,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
return nil, prepareError(errorGeneric)
}
const consoleVersion = "minio/console:v0.4.2"
const consoleVersion = "minio/console:v0.4.3"
minInst.Spec.Console = &operator.ConsoleConfiguration{
Replicas: 1,
Image: consoleVersion,

View File

@@ -1016,7 +1016,7 @@ func Test_UpdateTenantAction(t *testing.T) {
},
params: admin_api.UpdateTenantParams{
Body: &models.UpdateTenantRequest{
ConsoleImage: "minio/console:v0.4.2",
ConsoleImage: "minio/console:v0.4.3",
},
},
},

View File

@@ -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.

View File

@@ -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": [

View File

@@ -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)
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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)
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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()
}

View File

@@ -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)

View File

@@ -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
}
})
}
}

View File

@@ -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"