Add list objects api (#291)

This includes the basic information of an object
This commit is contained in:
Cesar N
2020-09-29 14:34:51 -07:00
committed by GitHub
parent 8313a62f17
commit 7afd608faa
13 changed files with 1176 additions and 7 deletions

69
models/bucket_object.go Normal file
View File

@@ -0,0 +1,69 @@
// 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/strfmt"
"github.com/go-openapi/swag"
)
// BucketObject bucket object
//
// swagger:model bucketObject
type BucketObject struct {
// content type
ContentType string `json:"content_type,omitempty"`
// last modified
LastModified string `json:"last_modified,omitempty"`
// name
Name string `json:"name,omitempty"`
// size
Size int64 `json:"size,omitempty"`
}
// Validate validates this bucket object
func (m *BucketObject) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *BucketObject) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *BucketObject) UnmarshalBinary(b []byte) error {
var res BucketObject
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,100 @@
// 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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ListObjectsResponse list objects response
//
// swagger:model listObjectsResponse
type ListObjectsResponse struct {
// list of resulting objects
Objects []*BucketObject `json:"objects"`
// number of objects
Total int64 `json:"total,omitempty"`
}
// Validate validates this list objects response
func (m *ListObjectsResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateObjects(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ListObjectsResponse) validateObjects(formats strfmt.Registry) error {
if swag.IsZero(m.Objects) { // not required
return nil
}
for i := 0; i < len(m.Objects); i++ {
if swag.IsZero(m.Objects[i]) { // not required
continue
}
if m.Objects[i] != nil {
if err := m.Objects[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("objects" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *ListObjectsResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ListObjectsResponse) UnmarshalBinary(b []byte) error {
var res ListObjectsResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -53,6 +53,7 @@ type MinioClient interface {
removeBucket(ctx context.Context, bucketName string) error removeBucket(ctx context.Context, bucketName string) error
getBucketNotification(ctx context.Context, bucketName string) (config notification.Configuration, err error) getBucketNotification(ctx context.Context, bucketName string) (config notification.Configuration, err error)
getBucketPolicy(ctx context.Context, bucketName string) (string, error) getBucketPolicy(ctx context.Context, bucketName string) (string, error)
listObjects(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
} }
// Interface implementation // Interface implementation
@@ -110,6 +111,11 @@ func (c minioClient) getBucketReplication(ctx context.Context, bucketName string
return c.client.GetBucketReplication(ctx, bucketName) return c.client.GetBucketReplication(ctx, bucketName)
} }
// implements minio.listObjects(ctx)
func (c minioClient) listObjects(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
return c.client.ListObjects(ctx, bucket, opts)
}
// MCClient interface with all functions to be implemented // MCClient interface with all functions to be implemented
// by mock when testing, it should include all mc/S3Client respective api calls // by mock when testing, it should include all mc/S3Client respective api calls
// that are used within this project. // that are used within this project.

View File

@@ -118,6 +118,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
registerNodesHandlers(api) registerNodesHandlers(api)
// Register Parity' handlers // Register Parity' handlers
registerParityHandlers(api) registerParityHandlers(api)
// Register Object's Handlers
registerObjectsHandlers(api)
api.PreServerShutdown = func() {} api.PreServerShutdown = func() {}

View File

@@ -341,6 +341,47 @@ func init() {
} }
} }
}, },
"/buckets/{bucket_name}/objects": {
"get": {
"tags": [
"UserAPI"
],
"summary": "List Objects",
"operationId": "ListObjects",
"parameters": [
{
"type": "string",
"name": "bucket_name",
"in": "path",
"required": true
},
{
"type": "string",
"name": "prefix",
"in": "query"
},
{
"type": "boolean",
"name": "recursive",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/listObjectsResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/buckets/{bucket_name}/replication": { "/buckets/{bucket_name}/replication": {
"get": { "get": {
"tags": [ "tags": [
@@ -2413,6 +2454,24 @@ func init() {
} }
} }
}, },
"bucketObject": {
"type": "object",
"properties": {
"content_type": {
"type": "string"
},
"last_modified": {
"type": "string"
},
"name": {
"type": "string"
},
"size": {
"type": "integer",
"format": "int64"
}
}
},
"bucketReplicationDestination": { "bucketReplicationDestination": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2978,6 +3037,23 @@ func init() {
} }
} }
}, },
"listObjectsResponse": {
"type": "object",
"properties": {
"objects": {
"type": "array",
"title": "list of resulting objects",
"items": {
"$ref": "#/definitions/bucketObject"
}
},
"total": {
"type": "integer",
"format": "int64",
"title": "number of objects"
}
}
},
"listPoliciesResponse": { "listPoliciesResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4505,6 +4581,47 @@ func init() {
} }
} }
}, },
"/buckets/{bucket_name}/objects": {
"get": {
"tags": [
"UserAPI"
],
"summary": "List Objects",
"operationId": "ListObjects",
"parameters": [
{
"type": "string",
"name": "bucket_name",
"in": "path",
"required": true
},
{
"type": "string",
"name": "prefix",
"in": "query"
},
{
"type": "boolean",
"name": "recursive",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/listObjectsResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/buckets/{bucket_name}/replication": { "/buckets/{bucket_name}/replication": {
"get": { "get": {
"tags": [ "tags": [
@@ -7100,6 +7217,24 @@ func init() {
} }
} }
}, },
"bucketObject": {
"type": "object",
"properties": {
"content_type": {
"type": "string"
},
"last_modified": {
"type": "string"
},
"name": {
"type": "string"
},
"size": {
"type": "integer",
"format": "int64"
}
}
},
"bucketReplicationDestination": { "bucketReplicationDestination": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -7665,6 +7800,23 @@ func init() {
} }
} }
}, },
"listObjectsResponse": {
"type": "object",
"properties": {
"objects": {
"type": "array",
"title": "list of resulting objects",
"items": {
"$ref": "#/definitions/bucketObject"
}
},
"total": {
"type": "integer",
"format": "int64",
"title": "number of objects"
}
}
},
"listPoliciesResponse": { "listPoliciesResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -162,6 +162,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPIListGroupsHandler: admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, principal *models.Principal) middleware.Responder { AdminAPIListGroupsHandler: admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListGroups has not yet been implemented") return middleware.NotImplemented("operation admin_api.ListGroups has not yet been implemented")
}), }),
UserAPIListObjectsHandler: user_api.ListObjectsHandlerFunc(func(params user_api.ListObjectsParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.ListObjects has not yet been implemented")
}),
AdminAPIListPoliciesHandler: admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, principal *models.Principal) middleware.Responder { AdminAPIListPoliciesHandler: admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListPolicies has not yet been implemented") return middleware.NotImplemented("operation admin_api.ListPolicies has not yet been implemented")
}), }),
@@ -376,6 +379,8 @@ type ConsoleAPI struct {
AdminAPIListConfigHandler admin_api.ListConfigHandler AdminAPIListConfigHandler admin_api.ListConfigHandler
// AdminAPIListGroupsHandler sets the operation handler for the list groups operation // AdminAPIListGroupsHandler sets the operation handler for the list groups operation
AdminAPIListGroupsHandler admin_api.ListGroupsHandler AdminAPIListGroupsHandler admin_api.ListGroupsHandler
// UserAPIListObjectsHandler sets the operation handler for the list objects operation
UserAPIListObjectsHandler user_api.ListObjectsHandler
// AdminAPIListPoliciesHandler sets the operation handler for the list policies operation // AdminAPIListPoliciesHandler sets the operation handler for the list policies operation
AdminAPIListPoliciesHandler admin_api.ListPoliciesHandler AdminAPIListPoliciesHandler admin_api.ListPoliciesHandler
// UserAPIListRemoteBucketsHandler sets the operation handler for the list remote buckets operation // UserAPIListRemoteBucketsHandler sets the operation handler for the list remote buckets operation
@@ -614,6 +619,9 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPIListGroupsHandler == nil { if o.AdminAPIListGroupsHandler == nil {
unregistered = append(unregistered, "admin_api.ListGroupsHandler") unregistered = append(unregistered, "admin_api.ListGroupsHandler")
} }
if o.UserAPIListObjectsHandler == nil {
unregistered = append(unregistered, "user_api.ListObjectsHandler")
}
if o.AdminAPIListPoliciesHandler == nil { if o.AdminAPIListPoliciesHandler == nil {
unregistered = append(unregistered, "admin_api.ListPoliciesHandler") unregistered = append(unregistered, "admin_api.ListPoliciesHandler")
} }
@@ -948,6 +956,10 @@ func (o *ConsoleAPI) initHandlerCache() {
if o.handlers["GET"] == nil { if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler) o.handlers["GET"] = make(map[string]http.Handler)
} }
o.handlers["GET"]["/buckets/{bucket_name}/objects"] = user_api.NewListObjects(o.context, o.UserAPIListObjectsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/policies"] = admin_api.NewListPolicies(o.context, o.AdminAPIListPoliciesHandler) o.handlers["GET"]["/policies"] = admin_api.NewListPolicies(o.context, o.AdminAPIListPoliciesHandler)
if o.handlers["GET"] == nil { if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler) 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"
)
// ListObjectsHandlerFunc turns a function with the right signature into a list objects handler
type ListObjectsHandlerFunc func(ListObjectsParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn ListObjectsHandlerFunc) Handle(params ListObjectsParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// ListObjectsHandler interface for that can handle valid list objects params
type ListObjectsHandler interface {
Handle(ListObjectsParams, *models.Principal) middleware.Responder
}
// NewListObjects creates a new http.Handler for the list objects operation
func NewListObjects(ctx *middleware.Context, handler ListObjectsHandler) *ListObjects {
return &ListObjects{Context: ctx, Handler: handler}
}
/*ListObjects swagger:route GET /buckets/{bucket_name}/objects UserAPI listObjects
List Objects
*/
type ListObjects struct {
Context *middleware.Context
Handler ListObjectsHandler
}
func (o *ListObjects) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
}
var Params = NewListObjectsParams()
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,151 @@
// 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/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewListObjectsParams creates a new ListObjectsParams object
// no default values defined in spec.
func NewListObjectsParams() ListObjectsParams {
return ListObjectsParams{}
}
// ListObjectsParams contains all the bound params for the list objects operation
// typically these are obtained from a http.Request
//
// swagger:parameters ListObjects
type ListObjectsParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*
Required: true
In: path
*/
BucketName string
/*
In: query
*/
Prefix *string
/*
In: query
*/
Recursive *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 NewListObjectsParams() beforehand.
func (o *ListObjectsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
qs := runtime.Values(r.URL.Query())
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)
}
qRecursive, qhkRecursive, _ := qs.GetOK("recursive")
if err := o.bindRecursive(qRecursive, qhkRecursive, 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 *ListObjectsParams) 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 *ListObjectsParams) bindPrefix(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
return nil
}
o.Prefix = &raw
return nil
}
// bindRecursive binds and validates parameter Recursive from query.
func (o *ListObjectsParams) bindRecursive(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
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("recursive", "query", "bool", raw)
}
o.Recursive = &value
return nil
}

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 swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/minio/console/models"
)
// ListObjectsOKCode is the HTTP code returned for type ListObjectsOK
const ListObjectsOKCode int = 200
/*ListObjectsOK A successful response.
swagger:response listObjectsOK
*/
type ListObjectsOK struct {
/*
In: Body
*/
Payload *models.ListObjectsResponse `json:"body,omitempty"`
}
// NewListObjectsOK creates ListObjectsOK with default headers values
func NewListObjectsOK() *ListObjectsOK {
return &ListObjectsOK{}
}
// WithPayload adds the payload to the list objects o k response
func (o *ListObjectsOK) WithPayload(payload *models.ListObjectsResponse) *ListObjectsOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list objects o k response
func (o *ListObjectsOK) SetPayload(payload *models.ListObjectsResponse) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListObjectsOK) 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
}
}
}
/*ListObjectsDefault Generic error response.
swagger:response listObjectsDefault
*/
type ListObjectsDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewListObjectsDefault creates ListObjectsDefault with default headers values
func NewListObjectsDefault(code int) *ListObjectsDefault {
if code <= 0 {
code = 500
}
return &ListObjectsDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the list objects default response
func (o *ListObjectsDefault) WithStatusCode(code int) *ListObjectsDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the list objects default response
func (o *ListObjectsDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the list objects default response
func (o *ListObjectsDefault) WithPayload(payload *models.Error) *ListObjectsDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list objects default response
func (o *ListObjectsDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListObjectsDefault) 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,141 @@
// 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"
"github.com/go-openapi/swag"
)
// ListObjectsURL generates an URL for the list objects operation
type ListObjectsURL struct {
BucketName string
Prefix *string
Recursive *bool
_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 *ListObjectsURL) WithBasePath(bp string) *ListObjectsURL {
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 *ListObjectsURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *ListObjectsURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/buckets/{bucket_name}/objects"
bucketName := o.BucketName
if bucketName != "" {
_path = strings.Replace(_path, "{bucket_name}", bucketName, -1)
} else {
return nil, errors.New("bucketName is required on ListObjectsURL")
}
_basePath := o._basePath
if _basePath == "" {
_basePath = "/api/v1"
}
_result.Path = golangswaggerpaths.Join(_basePath, _path)
qs := make(url.Values)
var prefixQ string
if o.Prefix != nil {
prefixQ = *o.Prefix
}
if prefixQ != "" {
qs.Set("prefix", prefixQ)
}
var recursiveQ string
if o.Recursive != nil {
recursiveQ = swag.FormatBool(*o.Recursive)
}
if recursiveQ != "" {
qs.Set("recursive", recursiveQ)
}
_result.RawQuery = qs.Encode()
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *ListObjectsURL) 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 *ListObjectsURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *ListObjectsURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on ListObjectsURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on ListObjectsURL")
}
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 *ListObjectsURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

93
restapi/user_objects.go Normal file
View File

@@ -0,0 +1,93 @@
// 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 restapi
import (
"context"
"time"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/user_api"
"github.com/minio/minio-go/v7"
)
func registerObjectsHandlers(api *operations.ConsoleAPI) {
// list objects
api.UserAPIListObjectsHandler = user_api.ListObjectsHandlerFunc(func(params user_api.ListObjectsParams, session *models.Principal) middleware.Responder {
resp, err := getListObjectsResponse(session, params)
if err != nil {
return user_api.NewListObjectsDefault(int(err.Code)).WithPayload(err)
}
return user_api.NewListObjectsOK().WithPayload(resp)
})
}
// listBucketObjects gets an array of objects in a bucket
func listBucketObjects(ctx context.Context, client MinioClient, bucketName string, prefix string, recursive bool) ([]*models.BucketObject, error) {
var objects []*models.BucketObject
for lsObj := range client.listObjects(ctx, bucketName, minio.ListObjectsOptions{Prefix: prefix, Recursive: recursive}) {
if lsObj.Err != nil {
return nil, lsObj.Err
}
obj := &models.BucketObject{
Name: lsObj.Key,
Size: lsObj.Size,
LastModified: lsObj.LastModified.String(),
ContentType: lsObj.ContentType,
}
objects = append(objects, obj)
}
return objects, nil
}
// getListObjectsResponse returns a list of objects
func getListObjectsResponse(session *models.Principal, params user_api.ListObjectsParams) (*models.ListObjectsResponse, *models.Error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
var prefix string
var recursive bool
if params.Prefix != nil {
prefix = *params.Prefix
}
if params.Recursive != nil {
recursive = *params.Recursive
}
// bucket request needed to proceed
if params.BucketName == "" {
return nil, prepareError(errBucketNameNotInRequest)
}
mClient, err := newMinioClient(session)
if err != nil {
return nil, prepareError(err)
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
objs, err := listBucketObjects(ctx, minioClient, params.BucketName, prefix, recursive)
if err != nil {
return nil, prepareError(err)
}
resp := &models.ListObjectsResponse{
Objects: objs,
Total: int64(len(objs)),
}
return resp, nil
}

View File

@@ -0,0 +1,162 @@
// 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 restapi
import (
"context"
"encoding/json"
"errors"
"reflect"
"testing"
"time"
"github.com/minio/console/models"
"github.com/minio/minio-go/v7"
)
var minioListObjectsMock func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
// mock function of listObjects() needed for list objects
func (ac minioClientMock) listObjects(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
return minioListObjectsMock(ctx, bucket, opts)
}
func Test_listObjects(t *testing.T) {
ctx := context.Background()
t1 := time.Now()
minClient := minioClientMock{}
type args struct {
bucketName string
prefix string
recursive bool
listFunc func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
}
tests := []struct {
test string
args args
expectedResp []*models.BucketObject
wantError error
}{
{
test: "Return objects",
args: args{
bucketName: "bucket1",
prefix: "prefix",
recursive: true,
listFunc: func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objectStatCh := make(chan minio.ObjectInfo, 1)
go func(objectStatCh chan<- minio.ObjectInfo) {
defer close(objectStatCh)
for _, bucket := range []minio.ObjectInfo{
minio.ObjectInfo{
Key: "obj1",
LastModified: t1,
Size: int64(1024),
ContentType: "content",
},
minio.ObjectInfo{
Key: "obj2",
LastModified: t1,
Size: int64(512),
ContentType: "content",
},
} {
objectStatCh <- bucket
}
}(objectStatCh)
return objectStatCh
},
},
expectedResp: []*models.BucketObject{
&models.BucketObject{
Name: "obj1",
LastModified: t1.String(),
Size: int64(1024),
ContentType: "content",
}, &models.BucketObject{
Name: "obj2",
LastModified: t1.String(),
Size: int64(512),
ContentType: "content",
},
},
wantError: nil,
},
{
test: "Return zero objects",
args: args{
bucketName: "bucket1",
prefix: "prefix",
recursive: true,
listFunc: func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objectStatCh := make(chan minio.ObjectInfo, 1)
defer close(objectStatCh)
return objectStatCh
},
},
expectedResp: nil,
wantError: nil,
},
{
test: "Handle error if present on object",
args: args{
bucketName: "bucket1",
prefix: "prefix",
recursive: true,
listFunc: func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objectStatCh := make(chan minio.ObjectInfo, 1)
go func(objectStatCh chan<- minio.ObjectInfo) {
defer close(objectStatCh)
for _, bucket := range []minio.ObjectInfo{
minio.ObjectInfo{
Key: "obj2",
LastModified: t1,
Size: int64(512),
ContentType: "content",
},
minio.ObjectInfo{
Err: errors.New("error here"),
},
} {
objectStatCh <- bucket
}
}(objectStatCh)
return objectStatCh
},
},
expectedResp: nil,
wantError: errors.New("error here"),
},
}
for _, tt := range tests {
t.Run(tt.test, func(t *testing.T) {
minioListObjectsMock = tt.args.listFunc
resp, err := listBucketObjects(ctx, minClient, tt.args.bucketName, tt.args.prefix, tt.args.recursive)
if !reflect.DeepEqual(err, tt.wantError) {
t.Errorf("listBucketObjects() error: %v, wantErr: %v", err, tt.wantError)
return
}
if !reflect.DeepEqual(resp, tt.expectedResp) {
ji, _ := json.Marshal(resp)
vi, _ := json.Marshal(tt.expectedResp)
t.Errorf("\ngot: %s \nwant: %s", ji, vi)
}
})
}
}

View File

@@ -223,6 +223,35 @@ paths:
tags: tags:
- UserAPI - UserAPI
/buckets/{bucket_name}/objects:
get:
summary: List Objects
operationId: ListObjects
parameters:
- name: bucket_name
in: path
required: true
type: string
- name: prefix
in: query
required: false
type: string
- name: recursive
in: query
required: false
type: boolean
responses:
200:
description: A successful response.
schema:
$ref: "#/definitions/listObjectsResponse"
default:
description: Generic error response.
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
/buckets/{name}/set-policy: /buckets/{name}/set-policy:
put: put:
summary: Bucket Set Policy summary: Bucket Set Policy
@@ -335,10 +364,10 @@ paths:
summary: Bucket Replication summary: Bucket Replication
operationId: GetBucketReplication operationId: GetBucketReplication
parameters: parameters:
- name: bucket_name - name: bucket_name
in: path in: path
required: true required: true
type: string type: string
responses: responses:
200: 200:
description: A successful response. description: A successful response.
@@ -1503,6 +1532,7 @@ definitions:
- PUBLIC - PUBLIC
- CUSTOM - CUSTOM
default: PRIVATE default: PRIVATE
bucket: bucket:
type: object type: object
required: required:
@@ -1518,6 +1548,7 @@ definitions:
$ref: "#/definitions/bucketAccess" $ref: "#/definitions/bucketAccess"
creation_date: creation_date:
type: string type: string
listBucketsResponse: listBucketsResponse:
type: object type: object
properties: properties:
@@ -1530,6 +1561,33 @@ definitions:
type: integer type: integer
format: int64 format: int64
title: number of buckets accessible to tenant user title: number of buckets accessible to tenant user
listObjectsResponse:
type: object
properties:
objects:
type: array
items:
$ref: "#/definitions/bucketObject"
title: list of resulting objects
total:
type: integer
format: int64
title: number of objects
bucketObject:
type: object
properties:
name:
type: string
size:
type: integer
format: int64
content_type:
type: string
last_modified:
type: string
makeBucketRequest: makeBucketRequest:
type: object type: object
required: required:
@@ -2298,7 +2356,7 @@ definitions:
$ref: "#/definitions/encryptionConfiguration" $ref: "#/definitions/encryptionConfiguration"
console: console:
type: object type: object
$ref: '#/definitions/consoleConfiguration' $ref: "#/definitions/consoleConfiguration"
metadataFields: metadataFields:
type: object type: object
@@ -2379,7 +2437,7 @@ definitions:
consoleConfiguration: consoleConfiguration:
allOf: allOf:
- $ref: '#/definitions/metadataFields' - $ref: "#/definitions/metadataFields"
- type: object - type: object
properties: properties:
image: image:
@@ -2387,7 +2445,7 @@ definitions:
encryptionConfiguration: encryptionConfiguration:
allOf: allOf:
- $ref: '#/definitions/metadataFields' - $ref: "#/definitions/metadataFields"
- type: object - type: object
properties: properties:
image: image: