2020-04-02 12:51:51 -07:00
// This file is part of MinIO Console Server
2021-01-19 17:04:13 -06:00
// Copyright (c) 2021 MinIO, Inc.
2020-04-01 18:18:57 -07:00
//
// 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"
Multiple fixes for sub path and objects filename encoding (#1086)
- fix: objects with special characters (ie: /,&,%,*) won't open
- fix: create subdolders with special characters won't work, ie: /,&,%,*
- fix: view subfolders with special characters (ie: /,&,%,*) won't work
- refactor: browser breadcrumb
- fix: rewind enable/disable toggle button not working
- fix: undefined style for add bucket button in buckets page
- Added: validation for folder path naming
- refactor: encode prefix parameter using base64 to avoid url encode
issues
- fix: share link for versioned object won't work because of wrong
version_id
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-09-28 12:25:28 -07:00
"encoding/base64"
2020-04-01 18:18:57 -07:00
"encoding/json"
2022-05-05 13:44:10 -07:00
"errors"
2020-04-01 18:18:57 -07:00
"fmt"
"strings"
"time"
2022-12-01 20:55:21 -08:00
"github.com/minio/madmin-go/v2"
2022-04-11 16:20:30 -07:00
"github.com/minio/minio-go/v7"
2021-06-23 01:10:54 -05:00
"github.com/minio/mc/cmd"
2020-12-15 19:25:43 -06:00
"github.com/minio/mc/pkg/probe"
2020-10-25 12:56:23 -07:00
"github.com/minio/minio-go/v7/pkg/sse"
2021-11-11 18:36:18 -08:00
"github.com/minio/minio-go/v7/pkg/tags"
2020-09-28 12:46:08 -05:00
2020-04-01 18:18:57 -07:00
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
2020-07-26 00:34:17 -07:00
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
2022-04-27 11:45:04 -07:00
bucketApi "github.com/minio/console/restapi/operations/bucket"
2020-07-25 14:38:16 -07:00
"github.com/minio/minio-go/v7/pkg/policy"
2022-01-20 00:29:57 -07:00
"github.com/minio/minio-go/v7/pkg/replication"
2021-06-01 11:34:55 -07:00
minioIAMPolicy "github.com/minio/pkg/iam/policy"
2020-04-01 18:18:57 -07:00
)
2020-07-26 00:34:17 -07:00
func registerBucketsHandlers ( api * operations . ConsoleAPI ) {
2020-04-01 18:18:57 -07:00
// list buckets
2022-04-27 11:45:04 -07:00
api . BucketListBucketsHandler = bucketApi . ListBucketsHandlerFunc ( func ( params bucketApi . ListBucketsParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
listBucketsResponse , err := getListBucketsResponse ( session , params )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewListBucketsDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-04-01 18:18:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewListBucketsOK ( ) . WithPayload ( listBucketsResponse )
2020-04-01 18:18:57 -07:00
} )
// make bucket
2022-04-27 11:45:04 -07:00
api . BucketMakeBucketHandler = bucketApi . MakeBucketHandlerFunc ( func ( params bucketApi . MakeBucketParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
if err := getMakeBucketResponse ( session , params ) ; err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewMakeBucketDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-04-01 18:18:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewMakeBucketCreated ( )
2020-04-01 18:18:57 -07:00
} )
// delete bucket
2022-04-27 11:45:04 -07:00
api . BucketDeleteBucketHandler = bucketApi . DeleteBucketHandlerFunc ( func ( params bucketApi . DeleteBucketParams , session * models . Principal ) middleware . Responder {
2020-07-10 19:14:28 -07:00
if err := getDeleteBucketResponse ( session , params ) ; err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewMakeBucketDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-04-01 18:18:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewDeleteBucketNoContent ( )
2020-04-01 18:18:57 -07:00
} )
// get bucket info
2022-04-27 11:45:04 -07:00
api . BucketBucketInfoHandler = bucketApi . BucketInfoHandlerFunc ( func ( params bucketApi . BucketInfoParams , session * models . Principal ) middleware . Responder {
2020-07-10 19:14:28 -07:00
bucketInfoResp , err := getBucketInfoResponse ( session , params )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewBucketInfoDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-04-01 18:18:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewBucketInfoOK ( ) . WithPayload ( bucketInfoResp )
2020-04-01 18:18:57 -07:00
} )
// set bucket policy
2022-04-27 11:45:04 -07:00
api . BucketBucketSetPolicyHandler = bucketApi . BucketSetPolicyHandlerFunc ( func ( params bucketApi . BucketSetPolicyParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
bucketSetPolicyResp , err := getBucketSetPolicyResponse ( session , params )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewBucketSetPolicyDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-04-01 18:18:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewBucketSetPolicyOK ( ) . WithPayload ( bucketSetPolicyResp )
2020-04-01 18:18:57 -07:00
} )
2021-11-11 18:36:18 -08:00
// set bucket tags
2022-04-27 11:45:04 -07:00
api . BucketPutBucketTagsHandler = bucketApi . PutBucketTagsHandlerFunc ( func ( params bucketApi . PutBucketTagsParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
err := getPutBucketTagsResponse ( session , params )
2021-11-11 18:36:18 -08:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewPutBucketTagsDefault ( int ( err . Code ) ) . WithPayload ( err )
2021-11-11 18:36:18 -08:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewPutBucketTagsOK ( )
2021-11-11 18:36:18 -08:00
} )
2020-09-28 12:46:08 -05:00
// get bucket versioning
2022-04-27 11:45:04 -07:00
api . BucketGetBucketVersioningHandler = bucketApi . GetBucketVersioningHandlerFunc ( func ( params bucketApi . GetBucketVersioningParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
getBucketVersioning , err := getBucketVersionedResponse ( session , params )
2020-09-28 12:46:08 -05:00
if err != nil {
2022-04-28 12:55:06 -07:00
return bucketApi . NewGetBucketVersioningDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-09-28 12:46:08 -05:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketVersioningOK ( ) . WithPayload ( getBucketVersioning )
2020-09-28 12:46:08 -05:00
} )
2021-03-19 18:48:58 -06:00
// update bucket versioning
2022-04-27 11:45:04 -07:00
api . BucketSetBucketVersioningHandler = bucketApi . SetBucketVersioningHandlerFunc ( func ( params bucketApi . SetBucketVersioningParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
err := setBucketVersioningResponse ( session , params )
2021-03-19 18:48:58 -06:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewSetBucketVersioningDefault ( 500 ) . WithPayload ( err )
2021-03-19 18:48:58 -06:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewSetBucketVersioningCreated ( )
2021-03-19 18:48:58 -06:00
} )
2020-09-28 12:46:08 -05:00
// get bucket replication
2022-04-27 11:45:04 -07:00
api . BucketGetBucketReplicationHandler = bucketApi . GetBucketReplicationHandlerFunc ( func ( params bucketApi . GetBucketReplicationParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
getBucketReplication , err := getBucketReplicationResponse ( session , params )
2020-09-28 12:46:08 -05:00
if err != nil {
2022-04-28 12:55:06 -07:00
return bucketApi . NewGetBucketReplicationDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-09-28 12:46:08 -05:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketReplicationOK ( ) . WithPayload ( getBucketReplication )
2020-09-28 12:46:08 -05:00
} )
2022-01-20 00:29:57 -07:00
// get single bucket replication rule
2022-04-27 11:45:04 -07:00
api . BucketGetBucketReplicationRuleHandler = bucketApi . GetBucketReplicationRuleHandlerFunc ( func ( params bucketApi . GetBucketReplicationRuleParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
getBucketReplicationRule , err := getBucketReplicationRuleResponse ( session , params )
2022-01-20 00:29:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return bucketApi . NewGetBucketReplicationRuleDefault ( int ( err . Code ) ) . WithPayload ( err )
2022-01-20 00:29:57 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketReplicationRuleOK ( ) . WithPayload ( getBucketReplicationRule )
2022-01-20 00:29:57 -07:00
} )
2020-10-25 12:56:23 -07:00
// enable bucket encryption
2022-04-27 11:45:04 -07:00
api . BucketEnableBucketEncryptionHandler = bucketApi . EnableBucketEncryptionHandlerFunc ( func ( params bucketApi . EnableBucketEncryptionParams , session * models . Principal ) middleware . Responder {
2020-10-25 12:56:23 -07:00
if err := enableBucketEncryptionResponse ( session , params ) ; err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewEnableBucketEncryptionDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-10-25 12:56:23 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewEnableBucketEncryptionOK ( )
2020-10-25 12:56:23 -07:00
} )
// disable bucket encryption
2022-04-27 11:45:04 -07:00
api . BucketDisableBucketEncryptionHandler = bucketApi . DisableBucketEncryptionHandlerFunc ( func ( params bucketApi . DisableBucketEncryptionParams , session * models . Principal ) middleware . Responder {
2020-10-25 12:56:23 -07:00
if err := disableBucketEncryptionResponse ( session , params ) ; err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewDisableBucketEncryptionDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-10-25 12:56:23 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewDisableBucketEncryptionOK ( )
2020-10-25 12:56:23 -07:00
} )
// get bucket encryption info
2022-04-27 11:45:04 -07:00
api . BucketGetBucketEncryptionInfoHandler = bucketApi . GetBucketEncryptionInfoHandlerFunc ( func ( params bucketApi . GetBucketEncryptionInfoParams , session * models . Principal ) middleware . Responder {
2020-10-25 12:56:23 -07:00
response , err := getBucketEncryptionInfoResponse ( session , params )
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketEncryptionInfoDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-10-25 12:56:23 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketEncryptionInfoOK ( ) . WithPayload ( response )
2020-10-25 12:56:23 -07:00
} )
2020-12-03 13:45:45 -06:00
// set bucket retention config
2022-04-27 11:45:04 -07:00
api . BucketSetBucketRetentionConfigHandler = bucketApi . SetBucketRetentionConfigHandlerFunc ( func ( params bucketApi . SetBucketRetentionConfigParams , session * models . Principal ) middleware . Responder {
2020-12-03 13:45:45 -06:00
if err := getSetBucketRetentionConfigResponse ( session , params ) ; err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewSetBucketRetentionConfigDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-12-03 13:45:45 -06:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewSetBucketRetentionConfigOK ( )
2020-12-03 13:45:45 -06:00
} )
2020-12-15 19:25:43 -06:00
// get bucket retention config
2022-04-27 11:45:04 -07:00
api . BucketGetBucketRetentionConfigHandler = bucketApi . GetBucketRetentionConfigHandlerFunc ( func ( params bucketApi . GetBucketRetentionConfigParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
response , err := getBucketRetentionConfigResponse ( session , params )
2020-12-15 19:25:43 -06:00
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketRetentionConfigDefault ( int ( err . Code ) ) . WithPayload ( err )
2020-12-15 19:25:43 -06:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketRetentionConfigOK ( ) . WithPayload ( response )
2020-12-15 19:25:43 -06:00
} )
2021-03-22 16:28:07 -07:00
// get bucket object locking status
2022-04-27 11:45:04 -07:00
api . BucketGetBucketObjectLockingStatusHandler = bucketApi . GetBucketObjectLockingStatusHandlerFunc ( func ( params bucketApi . GetBucketObjectLockingStatusParams , session * models . Principal ) middleware . Responder {
2022-04-28 12:55:06 -07:00
getBucketObjectLockingStatus , err := getBucketObjectLockingResponse ( session , params )
2021-03-22 16:28:07 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return bucketApi . NewGetBucketObjectLockingStatusDefault ( int ( err . Code ) ) . WithPayload ( err )
2021-03-22 16:28:07 -07:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketObjectLockingStatusOK ( ) . WithPayload ( getBucketObjectLockingStatus )
2021-03-22 16:28:07 -07:00
} )
2021-06-23 01:10:54 -05:00
// get objects rewind for a bucket
2022-04-27 11:45:04 -07:00
api . BucketGetBucketRewindHandler = bucketApi . GetBucketRewindHandlerFunc ( func ( params bucketApi . GetBucketRewindParams , session * models . Principal ) middleware . Responder {
2021-06-23 01:10:54 -05:00
getBucketRewind , err := getBucketRewindResponse ( session , params )
if err != nil {
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketRewindDefault ( 500 ) . WithPayload ( err )
2021-06-23 01:10:54 -05:00
}
2022-04-27 11:45:04 -07:00
return bucketApi . NewGetBucketRewindOK ( ) . WithPayload ( getBucketRewind )
2021-06-23 01:10:54 -05:00
} )
2020-09-28 12:46:08 -05:00
}
2021-03-19 18:48:58 -06:00
type VersionState string
const (
VersionEnable VersionState = "enable"
VersionSuspend = "suspend"
)
// removeBucket deletes a bucket
func doSetVersioning ( client MCClient , state VersionState ) error {
err := client . setVersioning ( context . Background ( ) , string ( state ) )
if err != nil {
return err . Cause
}
return nil
}
2022-04-28 12:55:06 -07:00
func setBucketVersioningResponse ( session * models . Principal , params bucketApi . SetBucketVersioningParams ) * models . Error {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
defer cancel ( )
bucketName := params . BucketName
2021-03-19 18:48:58 -06:00
s3Client , err := newS3BucketClient ( session , bucketName , "" )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2021-03-19 18:48:58 -06:00
}
// create a mc S3Client interface implementation
// defining the client to be used
amcClient := mcClient { client : s3Client }
var versioningState VersionState = VersionSuspend
if params . Body . Versioning {
versioningState = VersionEnable
}
2021-03-22 16:28:07 -07:00
if err := doSetVersioning ( amcClient , versioningState ) ; err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , fmt . Errorf ( "error setting versioning for bucket: %s" , err ) )
2021-03-19 18:48:58 -06:00
}
return nil
}
2022-04-28 12:55:06 -07:00
func getBucketReplicationResponse ( session * models . Principal , params bucketApi . GetBucketReplicationParams ) ( * models . BucketReplicationResponse , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-09-28 12:46:08 -05:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-09-28 12:46:08 -05:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
// we will tolerate this call failing
2022-04-28 12:55:06 -07:00
res , err := minioClient . getBucketReplication ( ctx , params . BucketName )
2020-09-28 12:46:08 -05:00
if err != nil {
2022-04-28 12:55:06 -07:00
ErrorWithContext ( ctx , err )
2020-09-28 12:46:08 -05:00
}
var rules [ ] * models . BucketReplicationRule
for _ , rule := range res . Rules {
2021-05-27 16:25:00 -07:00
repDelMarkerStatus := false
if rule . DeleteMarkerReplication . Status == "enable" {
repDelMarkerStatus = true
}
repDelStatus := false
if rule . DeleteReplication . Status == "enable" {
repDelMarkerStatus = true
}
2020-09-28 12:46:08 -05:00
rules = append ( rules , & models . BucketReplicationRule {
2021-05-27 16:25:00 -07:00
DeleteMarkerReplication : repDelMarkerStatus ,
DeletesReplication : repDelStatus ,
2020-09-28 12:46:08 -05:00
Destination : & models . BucketReplicationDestination { Bucket : rule . Destination . Bucket } ,
2021-05-27 16:25:00 -07:00
Tags : rule . Tags ( ) ,
Prefix : rule . Prefix ( ) ,
2020-09-28 12:46:08 -05:00
ID : rule . ID ,
Priority : int32 ( rule . Priority ) ,
Status : string ( rule . Status ) ,
2022-01-20 00:29:57 -07:00
StorageClass : rule . Destination . StorageClass ,
2020-09-28 12:46:08 -05:00
} )
}
// serialize output
2021-07-19 12:24:35 -07:00
bucketRResponse := & models . BucketReplicationResponse {
2020-09-28 12:46:08 -05:00
Rules : rules ,
}
2021-07-19 12:24:35 -07:00
return bucketRResponse , nil
2020-09-28 12:46:08 -05:00
}
2022-04-28 12:55:06 -07:00
func getBucketReplicationRuleResponse ( session * models . Principal , params bucketApi . GetBucketReplicationRuleParams ) ( * models . BucketReplicationRule , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2022-01-20 00:29:57 -07:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2022-01-20 00:29:57 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2022-04-28 12:55:06 -07:00
replicationRules , err := minioClient . getBucketReplication ( ctx , params . BucketName )
2022-01-20 00:29:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2022-01-20 00:29:57 -07:00
}
var foundRule replication . Rule
found := false
for i := range replicationRules . Rules {
2022-04-28 12:55:06 -07:00
if replicationRules . Rules [ i ] . ID == params . RuleID {
2022-01-20 00:29:57 -07:00
foundRule = replicationRules . Rules [ i ]
found = true
break
}
}
if ! found {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , errors . New ( "no rule is set with this ID" ) )
2022-01-20 00:29:57 -07:00
}
repDelMarkerStatus := false
if foundRule . DeleteMarkerReplication . Status == "Enabled" {
repDelMarkerStatus = true
}
repDelStatus := false
if foundRule . DeleteReplication . Status == "Enabled" {
repDelStatus = true
}
existingObjects := false
if foundRule . ExistingObjectReplication . Status == "Enabled" {
existingObjects = true
}
metadataModifications := false
if foundRule . SourceSelectionCriteria . ReplicaModifications . Status == "Enabled" {
metadataModifications = true
}
returnRule := & models . BucketReplicationRule {
DeleteMarkerReplication : repDelMarkerStatus ,
DeletesReplication : repDelStatus ,
Destination : & models . BucketReplicationDestination { Bucket : foundRule . Destination . Bucket } ,
Tags : foundRule . Tags ( ) ,
Prefix : foundRule . Prefix ( ) ,
ID : foundRule . ID ,
Priority : int32 ( foundRule . Priority ) ,
Status : string ( foundRule . Status ) ,
StorageClass : foundRule . Destination . StorageClass ,
ExistingObjects : existingObjects ,
MetadataReplication : metadataModifications ,
}
return returnRule , nil
}
2022-04-28 12:55:06 -07:00
func getBucketVersionedResponse ( session * models . Principal , params bucketApi . GetBucketVersioningParams ) ( * models . BucketVersioningResponse , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-09-28 12:46:08 -05:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-09-28 12:46:08 -05:00
}
2021-07-19 12:24:35 -07:00
2020-09-28 12:46:08 -05:00
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
// we will tolerate this call failing
2022-04-28 12:55:06 -07:00
res , err := minioClient . getBucketVersioning ( ctx , params . BucketName )
2020-09-28 12:46:08 -05:00
if err != nil {
2022-04-28 12:55:06 -07:00
ErrorWithContext ( ctx , fmt . Errorf ( "error versioning bucket: %v" , err ) )
2020-09-28 12:46:08 -05:00
}
// serialize output
2021-07-19 12:24:35 -07:00
bucketVResponse := & models . BucketVersioningResponse {
2020-09-28 12:46:08 -05:00
IsVersioned : res . Status == "Enabled" ,
}
2021-07-19 12:24:35 -07:00
return bucketVResponse , nil
}
2021-11-15 12:24:37 -08:00
// getAccountBuckets fetches a list of all buckets allowed to that particular client from MinIO Servers
2021-11-18 08:25:01 -08:00
func getAccountBuckets ( ctx context . Context , client MinioAdmin ) ( [ ] * models . Bucket , error ) {
2021-07-19 11:48:50 -07:00
info , err := client . AccountInfo ( ctx )
2020-04-01 18:18:57 -07:00
if err != nil {
return [ ] * models . Bucket { } , err
}
var bucketInfos [ ] * models . Bucket
2020-05-18 13:36:18 -07:00
for _ , bucket := range info . Buckets {
2021-07-19 12:24:35 -07:00
bucketElem := & models . Bucket {
CreationDate : bucket . Created . Format ( time . RFC3339 ) ,
2021-09-20 11:13:34 -07:00
Details : & models . BucketDetails {
Quota : nil ,
} ,
RwAccess : & models . BucketRwAccess {
Read : bucket . Access . Read ,
Write : bucket . Access . Write ,
} ,
Name : swag . String ( bucket . Name ) ,
Objects : int64 ( bucket . Objects ) ,
Size : int64 ( bucket . Size ) ,
}
if bucket . Details != nil {
if bucket . Details . Tagging != nil {
bucketElem . Details . Tags = bucket . Details . Tagging . ToMap ( )
}
bucketElem . Details . Locking = bucket . Details . Locking
bucketElem . Details . Replication = bucket . Details . Replication
bucketElem . Details . Versioning = bucket . Details . Versioning
bucketElem . Details . VersioningSuspended = bucket . Details . VersioningSuspended
if bucket . Details . Quota != nil {
bucketElem . Details . Quota = & models . BucketDetailsQuota {
Quota : int64 ( bucket . Details . Quota . Quota ) ,
Type : string ( bucket . Details . Quota . Type ) ,
}
}
2021-07-19 12:24:35 -07:00
}
2021-09-20 11:13:34 -07:00
2020-04-01 18:18:57 -07:00
bucketInfos = append ( bucketInfos , bucketElem )
}
return bucketInfos , nil
}
// getListBucketsResponse performs listBuckets() and serializes it to the handler's output
2022-04-28 12:55:06 -07:00
func getListBucketsResponse ( session * models . Principal , params bucketApi . ListBucketsParams ) ( * models . ListBucketsResponse , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-04-01 18:18:57 -07:00
defer cancel ( )
2020-05-18 13:36:18 -07:00
2021-07-19 11:48:50 -07:00
mAdmin , err := NewMinioAdminClient ( session )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
2021-07-19 11:48:50 -07:00
adminClient := AdminClient { Client : mAdmin }
2021-11-18 08:25:01 -08:00
buckets , err := getAccountBuckets ( ctx , adminClient )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
2020-05-18 13:36:18 -07:00
2020-04-01 18:18:57 -07:00
// serialize output
listBucketsResponse := & models . ListBucketsResponse {
Buckets : buckets ,
Total : int64 ( len ( buckets ) ) ,
}
return listBucketsResponse , nil
}
// makeBucket creates a bucket for an specific minio client
2020-11-25 12:40:39 -06:00
func makeBucket ( ctx context . Context , client MinioClient , bucketName string , objectLocking bool ) error {
2020-04-01 18:18:57 -07:00
// creates a new bucket with bucketName with a context to control cancellations and timeouts.
2021-06-07 20:53:03 -07:00
return client . makeBucketWithContext ( ctx , bucketName , "" , objectLocking )
2020-04-06 09:59:19 -07:00
}
// getMakeBucketResponse performs makeBucket() to create a bucket with its access policy
2022-04-28 12:55:06 -07:00
func getMakeBucketResponse ( session * models . Principal , params bucketApi . MakeBucketParams ) * models . Error {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-04-06 09:59:19 -07:00
defer cancel ( )
// bucket request needed to proceed
2022-04-28 12:55:06 -07:00
br := params . Body
2020-04-06 09:59:19 -07:00
if br == nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , ErrBucketBodyNotInRequest )
2020-04-06 09:59:19 -07:00
}
2020-07-10 19:14:28 -07:00
mClient , err := newMinioClient ( session )
2020-04-06 09:59:19 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-04-06 09:59:19 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2021-03-22 16:28:07 -07:00
// if we need retention, then object locking needs to be enabled
if br . Retention != nil {
br . Locking = true
}
if err := makeBucket ( ctx , minioClient , * br . Name , br . Locking ) ; err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
2020-11-25 12:40:39 -06:00
2022-04-28 12:55:06 -07:00
// make sure to delete bucket if an errors occurs after bucket was created
2020-12-11 10:22:25 -06:00
defer func ( ) {
if err != nil {
2022-04-28 12:55:06 -07:00
ErrorWithContext ( ctx , fmt . Errorf ( "error creating bucket: %v" , err ) )
2020-12-11 10:22:25 -06:00
if err := removeBucket ( minioClient , * br . Name ) ; err != nil {
2022-04-28 12:55:06 -07:00
ErrorWithContext ( ctx , fmt . Errorf ( "error removing bucket: %v" , err ) )
2020-12-11 10:22:25 -06:00
}
}
} ( )
2021-03-22 16:28:07 -07:00
// enable versioning if indicated or retention enabled
if br . Versioning || br . Retention != nil {
s3Client , err := newS3BucketClient ( session , * br . Name , "" )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2021-03-22 16:28:07 -07:00
}
// create a mc S3Client interface implementation
// defining the client to be used
amcClient := mcClient { client : s3Client }
if err = doSetVersioning ( amcClient , VersionEnable ) ; err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , fmt . Errorf ( "error setting versioning for bucket: %s" , err ) )
2021-03-22 16:28:07 -07:00
}
}
2020-10-01 18:59:20 -07:00
// if it has support for
if br . Quota != nil && br . Quota . Enabled != nil && * br . Quota . Enabled {
2021-07-19 11:48:50 -07:00
mAdmin , err := NewMinioAdminClient ( session )
2020-10-01 18:59:20 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-10-01 18:59:20 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
2021-07-19 11:48:50 -07:00
adminClient := AdminClient { Client : mAdmin }
2020-10-01 18:59:20 -07:00
// we will tolerate this call failing
if err := setBucketQuota ( ctx , & adminClient , br . Name , br . Quota ) ; err != nil {
2022-04-28 12:55:06 -07:00
ErrorWithContext ( ctx , fmt . Errorf ( "error versioning bucket: %v" , err ) )
2020-10-01 18:59:20 -07:00
}
}
2020-12-11 10:22:25 -06:00
// Set Bucket Retention Configuration if defined
if br . Retention != nil {
2021-06-08 12:35:39 -07:00
err = setBucketRetentionConfig ( ctx , minioClient , * br . Name , * br . Retention . Mode , * br . Retention . Unit , br . Retention . Validity )
2020-12-11 10:22:25 -06:00
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-12-11 10:22:25 -06:00
}
}
2020-04-01 18:18:57 -07:00
return nil
}
// setBucketAccessPolicy set the access permissions on an existing bucket.
2021-12-28 18:21:29 -08:00
func setBucketAccessPolicy ( ctx context . Context , client MinioClient , bucketName string , access models . BucketAccess , policyDefinition string ) error {
2020-04-01 18:18:57 -07:00
if strings . TrimSpace ( bucketName ) == "" {
return fmt . Errorf ( "error: bucket name not present" )
}
if strings . TrimSpace ( string ( access ) ) == "" {
return fmt . Errorf ( "error: bucket access not present" )
}
// Prepare policyJSON corresponding to the access type
2021-12-28 18:21:29 -08:00
if access != models . BucketAccessPRIVATE && access != models . BucketAccessPUBLIC && access != models . BucketAccessCUSTOM {
2020-04-01 18:18:57 -07:00
return fmt . Errorf ( "access: `%s` not supported" , access )
}
bucketAccessPolicy := policy . BucketAccessPolicy { Version : minioIAMPolicy . DefaultVersion }
2021-12-28 18:21:29 -08:00
if access == models . BucketAccessCUSTOM {
err := client . setBucketPolicyWithContext ( ctx , bucketName , policyDefinition )
if err != nil {
return err
}
return nil
}
bucketPolicy := consoleAccess2policyAccess ( access )
2020-04-01 18:18:57 -07:00
bucketAccessPolicy . Statements = policy . SetPolicy ( bucketAccessPolicy . Statements ,
2021-11-15 17:48:25 -08:00
bucketPolicy , bucketName , "" )
2020-04-01 18:18:57 -07:00
policyJSON , err := json . Marshal ( bucketAccessPolicy )
if err != nil {
return err
}
return client . setBucketPolicyWithContext ( ctx , bucketName , string ( policyJSON ) )
}
// getBucketSetPolicyResponse calls setBucketAccessPolicy() to set a access policy to a bucket
2022-08-05 08:07:38 -07:00
// and returns the serialized output.
2022-04-28 12:55:06 -07:00
func getBucketSetPolicyResponse ( session * models . Principal , params bucketApi . BucketSetPolicyParams ) ( * models . Bucket , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-04-01 18:18:57 -07:00
defer cancel ( )
2021-12-28 18:21:29 -08:00
// get updated bucket details and return it
2020-07-10 19:14:28 -07:00
mClient , err := newMinioClient ( session )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2021-12-28 18:21:29 -08:00
2022-02-01 21:48:58 -07:00
mAdmin , err := NewMinioAdminClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2022-02-01 21:48:58 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient { Client : mAdmin }
2022-04-28 12:55:06 -07:00
bucketName := params . Name
req := params . Body
2021-12-28 18:21:29 -08:00
if err := setBucketAccessPolicy ( ctx , minioClient , bucketName , * req . Access , req . Definition ) ; err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
2021-12-28 18:21:29 -08:00
// set bucket access policy
2022-02-01 21:48:58 -07:00
bucket , err := getBucketInfo ( ctx , minioClient , adminClient , bucketName )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
return bucket , nil
}
2021-11-11 18:36:18 -08:00
// putBucketTags sets tags for a bucket
2022-04-28 12:55:06 -07:00
func getPutBucketTagsResponse ( session * models . Principal , params bucketApi . PutBucketTagsParams ) * models . Error {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2021-11-11 18:36:18 -08:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2021-11-11 18:36:18 -08:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2022-04-28 12:55:06 -07:00
req := params . Body
bucketName := params . BucketName
2021-11-11 18:36:18 -08:00
newTagSet , err := tags . NewTags ( req . Tags , true )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2021-11-11 18:36:18 -08:00
}
err = minioClient . SetBucketTagging ( ctx , bucketName , newTagSet )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2021-11-11 18:36:18 -08:00
}
return nil
}
2020-04-01 18:18:57 -07:00
// removeBucket deletes a bucket
func removeBucket ( client MinioClient , bucketName string ) error {
2020-07-25 14:38:16 -07:00
return client . removeBucket ( context . Background ( ) , bucketName )
2020-04-01 18:18:57 -07:00
}
// getDeleteBucketResponse performs removeBucket() to delete a bucket
2022-04-27 11:45:04 -07:00
func getDeleteBucketResponse ( session * models . Principal , params bucketApi . DeleteBucketParams ) * models . Error {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
defer cancel ( )
2020-04-01 18:18:57 -07:00
if params . Name == "" {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , ErrBucketNameNotInRequest )
2020-04-01 18:18:57 -07:00
}
bucketName := params . Name
2020-07-10 19:14:28 -07:00
mClient , err := newMinioClient ( session )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2020-09-04 20:32:57 -07:00
if err := removeBucket ( minioClient , bucketName ) ; err != nil {
2022-05-11 09:39:43 -07:00
resp := ErrorWithContext ( ctx , err )
errResp := minio . ToErrorResponse ( err )
if errResp . Code == "NoSuchBucket" {
resp . Code = 404
}
return resp
2020-09-04 20:32:57 -07:00
}
return nil
2020-04-01 18:18:57 -07:00
}
// getBucketInfo return bucket information including name, policy access, size and creation date
2022-02-01 21:48:58 -07:00
func getBucketInfo ( ctx context . Context , client MinioClient , adminClient MinioAdmin , bucketName string ) ( * models . Bucket , error ) {
2021-11-02 17:34:39 -07:00
var bucketAccess models . BucketAccess
policyStr , err := client . getBucketPolicy ( context . Background ( ) , bucketName )
if err != nil {
2022-04-28 12:55:06 -07:00
// we can tolerate this errors
ErrorWithContext ( ctx , fmt . Errorf ( "error getting bucket policy: %v" , err ) )
2021-11-02 17:34:39 -07:00
}
2020-04-01 18:18:57 -07:00
if policyStr == "" {
2021-12-28 18:21:29 -08:00
bucketAccess = models . BucketAccessPRIVATE
2020-04-01 18:18:57 -07:00
} else {
var p policy . BucketAccessPolicy
if err = json . Unmarshal ( [ ] byte ( policyStr ) , & p ) ; err != nil {
return nil , err
}
2021-12-28 18:21:29 -08:00
policyAccess := policy . GetPolicy ( p . Statements , bucketName , "" )
if len ( p . Statements ) > 0 && policyAccess == policy . BucketPolicyNone {
bucketAccess = models . BucketAccessCUSTOM
} else {
bucketAccess = policyAccess2consoleAccess ( policyAccess )
}
2020-04-01 18:18:57 -07:00
}
2021-11-11 18:36:18 -08:00
bucketTags , err := client . GetBucketTagging ( ctx , bucketName )
2021-11-18 08:25:01 -08:00
if err != nil {
2022-04-28 12:55:06 -07:00
// we can tolerate this errors
ErrorWithContext ( ctx , fmt . Errorf ( "error getting bucket tags: %v" , err ) )
2021-11-18 08:25:01 -08:00
}
bucketDetails := & models . BucketDetails { }
if bucketTags != nil {
bucketDetails . Tags = bucketTags . ToMap ( )
}
2022-02-01 21:48:58 -07:00
info , err := adminClient . AccountInfo ( ctx )
if err != nil {
return nil , err
}
var bucketInfo madmin . BucketAccessInfo
for _ , bucket := range info . Buckets {
if bucket . Name == bucketName {
bucketInfo = bucket
}
}
2021-11-18 08:25:01 -08:00
return & models . Bucket {
Name : & bucketName ,
Access : & bucketAccess ,
2021-12-28 18:21:29 -08:00
Definition : policyStr ,
2022-02-01 21:48:58 -07:00
CreationDate : bucketInfo . Created . Format ( time . RFC3339 ) ,
Size : int64 ( bucketInfo . Size ) ,
2021-11-18 08:25:01 -08:00
Details : bucketDetails ,
2022-02-01 21:48:58 -07:00
Objects : int64 ( bucketInfo . Objects ) ,
2021-11-18 08:25:01 -08:00
} , nil
2020-04-01 18:18:57 -07:00
}
// getBucketInfoResponse calls getBucketInfo() to get the bucket's info
2022-04-27 11:45:04 -07:00
func getBucketInfoResponse ( session * models . Principal , params bucketApi . BucketInfoParams ) ( * models . Bucket , * models . Error ) {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2021-11-02 17:34:39 -07:00
defer cancel ( )
2020-07-10 19:14:28 -07:00
mClient , err := newMinioClient ( session )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2022-02-01 21:48:58 -07:00
mAdmin , err := NewMinioAdminClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2022-02-01 21:48:58 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient { Client : mAdmin }
bucket , err := getBucketInfo ( ctx , minioClient , adminClient , params . Name )
2020-04-01 18:18:57 -07:00
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-04-01 18:18:57 -07:00
}
return bucket , nil
}
2020-07-26 00:34:17 -07:00
// policyAccess2consoleAccess gets the equivalent of policy.BucketPolicy to models.BucketAccess
func policyAccess2consoleAccess ( bucketPolicy policy . BucketPolicy ) ( bucketAccess models . BucketAccess ) {
2020-04-01 18:18:57 -07:00
switch bucketPolicy {
case policy . BucketPolicyReadWrite :
bucketAccess = models . BucketAccessPUBLIC
case policy . BucketPolicyNone :
bucketAccess = models . BucketAccessPRIVATE
default :
bucketAccess = models . BucketAccessCUSTOM
}
return bucketAccess
}
2020-07-26 00:34:17 -07:00
// consoleAccess2policyAccess gets the equivalent of models.BucketAccess to policy.BucketPolicy
func consoleAccess2policyAccess ( bucketAccess models . BucketAccess ) ( bucketPolicy policy . BucketPolicy ) {
2020-04-01 18:18:57 -07:00
switch bucketAccess {
case models . BucketAccessPUBLIC :
bucketPolicy = policy . BucketPolicyReadWrite
case models . BucketAccessPRIVATE :
bucketPolicy = policy . BucketPolicyNone
}
return bucketPolicy
}
2020-10-25 12:56:23 -07:00
// enableBucketEncryption will enable bucket encryption based on two encryption algorithms, sse-s3 (server side encryption with external KMS) or sse-kms (aws s3 kms key)
func enableBucketEncryption ( ctx context . Context , client MinioClient , bucketName string , encryptionType models . BucketEncryptionType , kmsKeyID string ) error {
var config * sse . Configuration
switch encryptionType {
2021-06-08 12:35:39 -07:00
case models . BucketEncryptionTypeSseDashKms :
2020-10-25 12:56:23 -07:00
config = sse . NewConfigurationSSEKMS ( kmsKeyID )
2021-06-08 12:35:39 -07:00
case models . BucketEncryptionTypeSseDashS3 :
2020-10-25 12:56:23 -07:00
config = sse . NewConfigurationSSES3 ( )
default :
2022-04-28 12:55:06 -07:00
return ErrInvalidEncryptionAlgorithm
2020-10-25 12:56:23 -07:00
}
return client . setBucketEncryption ( ctx , bucketName , config )
}
// enableBucketEncryptionResponse calls enableBucketEncryption() to create new encryption configuration for provided bucket name
2022-04-27 11:45:04 -07:00
func enableBucketEncryptionResponse ( session * models . Principal , params bucketApi . EnableBucketEncryptionParams ) * models . Error {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-10-25 12:56:23 -07:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-10-25 12:56:23 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2021-06-08 12:35:39 -07:00
if err := enableBucketEncryption ( ctx , minioClient , params . BucketName , * params . Body . EncType , params . Body . KmsKeyID ) ; err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-10-25 12:56:23 -07:00
}
return nil
}
// disableBucketEncryption will disable bucket for the provided bucket name
func disableBucketEncryption ( ctx context . Context , client MinioClient , bucketName string ) error {
return client . removeBucketEncryption ( ctx , bucketName )
}
// disableBucketEncryptionResponse calls disableBucketEncryption()
2022-04-27 11:45:04 -07:00
func disableBucketEncryptionResponse ( session * models . Principal , params bucketApi . DisableBucketEncryptionParams ) * models . Error {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-10-25 12:56:23 -07:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-10-25 12:56:23 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
if err := disableBucketEncryption ( ctx , minioClient , params . BucketName ) ; err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-10-25 12:56:23 -07:00
}
return nil
}
func getBucketEncryptionInfo ( ctx context . Context , client MinioClient , bucketName string ) ( * models . BucketEncryptionInfo , error ) {
bucketInfo , err := client . getBucketEncryption ( ctx , bucketName )
if err != nil {
return nil , err
}
if len ( bucketInfo . Rules ) == 0 {
2022-04-28 12:55:06 -07:00
return nil , ErrDefault
2020-10-25 12:56:23 -07:00
}
return & models . BucketEncryptionInfo { Algorithm : bucketInfo . Rules [ 0 ] . Apply . SSEAlgorithm , KmsMasterKeyID : bucketInfo . Rules [ 0 ] . Apply . KmsMasterKeyID } , nil
}
2022-04-27 11:45:04 -07:00
func getBucketEncryptionInfoResponse ( session * models . Principal , params bucketApi . GetBucketEncryptionInfoParams ) ( * models . BucketEncryptionInfo , * models . Error ) {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-10-25 12:56:23 -07:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-10-25 12:56:23 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
bucketInfo , err := getBucketEncryptionInfo ( ctx , minioClient , params . BucketName )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , ErrSSENotConfigured , err )
2020-10-25 12:56:23 -07:00
}
return bucketInfo , nil
}
2020-12-03 13:45:45 -06:00
// setBucketRetentionConfig sets object lock configuration on a bucket
func setBucketRetentionConfig ( ctx context . Context , client MinioClient , bucketName string , mode models . ObjectRetentionMode , unit models . ObjectRetentionUnit , validity * int32 ) error {
if validity == nil {
return errors . New ( "retention validity can't be nil" )
}
var retentionMode minio . RetentionMode
switch mode {
case models . ObjectRetentionModeGovernance :
retentionMode = minio . Governance
case models . ObjectRetentionModeCompliance :
retentionMode = minio . Compliance
default :
return errors . New ( "invalid retention mode" )
}
var retentionUnit minio . ValidityUnit
switch unit {
case models . ObjectRetentionUnitDays :
retentionUnit = minio . Days
case models . ObjectRetentionUnitYears :
retentionUnit = minio . Years
default :
return errors . New ( "invalid retention unit" )
}
retentionValidity := uint ( * validity )
return client . setObjectLockConfig ( ctx , bucketName , & retentionMode , & retentionValidity , & retentionUnit )
}
2022-04-27 11:45:04 -07:00
func getSetBucketRetentionConfigResponse ( session * models . Principal , params bucketApi . SetBucketRetentionConfigParams ) * models . Error {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-12-03 13:45:45 -06:00
defer cancel ( )
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-12-03 13:45:45 -06:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
2021-06-08 12:35:39 -07:00
err = setBucketRetentionConfig ( ctx , minioClient , params . BucketName , * params . Body . Mode , * params . Body . Unit , params . Body . Validity )
2020-12-03 13:45:45 -06:00
if err != nil {
2022-04-28 12:55:06 -07:00
return ErrorWithContext ( ctx , err )
2020-12-03 13:45:45 -06:00
}
return nil
}
2020-12-15 19:25:43 -06:00
func getBucketRetentionConfig ( ctx context . Context , client MinioClient , bucketName string ) ( * models . GetBucketRetentionConfig , error ) {
m , v , u , err := client . getBucketObjectLockConfig ( ctx , bucketName )
if err != nil {
errResp := minio . ToErrorResponse ( probe . NewError ( err ) . ToGoError ( ) )
if errResp . Code == "ObjectLockConfigurationNotFoundError" {
return & models . GetBucketRetentionConfig { } , nil
}
return nil , err
}
2021-08-09 21:23:40 -07:00
// These values can be empty when all are empty, it means
// object was created with object locking enabled but
// does not have any default object locking configuration.
if m == nil && v == nil && u == nil {
return & models . GetBucketRetentionConfig { } , nil
}
2020-12-15 19:25:43 -06:00
var mode models . ObjectRetentionMode
var unit models . ObjectRetentionUnit
2021-08-09 21:23:40 -07:00
if m != nil {
switch * m {
case minio . Governance :
mode = models . ObjectRetentionModeGovernance
case minio . Compliance :
mode = models . ObjectRetentionModeCompliance
default :
return nil , errors . New ( "invalid retention mode" )
}
2020-12-15 19:25:43 -06:00
}
2021-08-09 21:23:40 -07:00
if u != nil {
switch * u {
case minio . Days :
unit = models . ObjectRetentionUnitDays
case minio . Years :
unit = models . ObjectRetentionUnitYears
default :
return nil , errors . New ( "invalid retention unit" )
}
}
var validity int32
if v != nil {
validity = int32 ( * v )
2020-12-15 19:25:43 -06:00
}
config := & models . GetBucketRetentionConfig {
Mode : mode ,
Unit : unit ,
2021-08-09 21:23:40 -07:00
Validity : validity ,
2020-12-15 19:25:43 -06:00
}
return config , nil
}
2022-04-28 12:55:06 -07:00
func getBucketRetentionConfigResponse ( session * models . Principal , params bucketApi . GetBucketRetentionConfigParams ) ( * models . GetBucketRetentionConfig , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2020-12-15 19:25:43 -06:00
defer cancel ( )
2022-04-28 12:55:06 -07:00
bucketName := params . BucketName
2020-12-15 19:25:43 -06:00
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-12-15 19:25:43 -06:00
}
2021-08-09 21:23:40 -07:00
2020-12-15 19:25:43 -06:00
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
config , err := getBucketRetentionConfig ( ctx , minioClient , bucketName )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2020-12-15 19:25:43 -06:00
}
return config , nil
}
2021-03-22 16:28:07 -07:00
2022-04-28 12:55:06 -07:00
func getBucketObjectLockingResponse ( session * models . Principal , params bucketApi . GetBucketObjectLockingStatusParams ) ( * models . BucketObLockingResponse , * models . Error ) {
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2021-03-22 16:28:07 -07:00
defer cancel ( )
2022-04-28 12:55:06 -07:00
bucketName := params . BucketName
2021-03-22 16:28:07 -07:00
mClient , err := newMinioClient ( session )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , fmt . Errorf ( "error creating MinIO Client: %v" , err ) )
2021-03-22 16:28:07 -07:00
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient { client : mClient }
// we will tolerate this call failing
_ , _ , _ , _ , err = minioClient . getObjectLockConfig ( ctx , bucketName )
if err != nil {
2021-08-09 21:23:40 -07:00
if minio . ToErrorResponse ( err ) . Code == "ObjectLockConfigurationNotFoundError" {
2021-03-22 16:28:07 -07:00
return & models . BucketObLockingResponse {
ObjectLockingEnabled : false ,
} , nil
}
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
2021-03-22 16:28:07 -07:00
}
// serialize output
2021-08-09 21:23:40 -07:00
return & models . BucketObLockingResponse {
2021-03-22 16:28:07 -07:00
ObjectLockingEnabled : true ,
2021-08-09 21:23:40 -07:00
} , nil
2021-03-22 16:28:07 -07:00
}
2021-06-23 01:10:54 -05:00
2022-04-27 11:45:04 -07:00
func getBucketRewindResponse ( session * models . Principal , params bucketApi . GetBucketRewindParams ) ( * models . RewindResponse , * models . Error ) {
2022-04-28 12:55:06 -07:00
ctx , cancel := context . WithCancel ( params . HTTPRequest . Context ( ) )
2021-06-23 01:10:54 -05:00
defer cancel ( )
2022-05-05 13:44:10 -07:00
prefix := ""
2021-06-23 01:10:54 -05:00
if params . Prefix != nil {
2021-10-19 13:00:13 -07:00
encodedPrefix := SanitizeEncodedPrefix ( * params . Prefix )
Multiple fixes for sub path and objects filename encoding (#1086)
- fix: objects with special characters (ie: /,&,%,*) won't open
- fix: create subdolders with special characters won't work, ie: /,&,%,*
- fix: view subfolders with special characters (ie: /,&,%,*) won't work
- refactor: browser breadcrumb
- fix: rewind enable/disable toggle button not working
- fix: undefined style for add bucket button in buckets page
- Added: validation for folder path naming
- refactor: encode prefix parameter using base64 to avoid url encode
issues
- fix: share link for versioned object won't work because of wrong
version_id
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-09-28 12:25:28 -07:00
decodedPrefix , err := base64 . StdEncoding . DecodeString ( encodedPrefix )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , err )
Multiple fixes for sub path and objects filename encoding (#1086)
- fix: objects with special characters (ie: /,&,%,*) won't open
- fix: create subdolders with special characters won't work, ie: /,&,%,*
- fix: view subfolders with special characters (ie: /,&,%,*) won't work
- refactor: browser breadcrumb
- fix: rewind enable/disable toggle button not working
- fix: undefined style for add bucket button in buckets page
- Added: validation for folder path naming
- refactor: encode prefix parameter using base64 to avoid url encode
issues
- fix: share link for versioned object won't work because of wrong
version_id
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-09-28 12:25:28 -07:00
}
prefix = string ( decodedPrefix )
2021-06-23 01:10:54 -05:00
}
s3Client , err := newS3BucketClient ( session , params . BucketName , prefix )
if err != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , fmt . Errorf ( "error creating S3Client: %v" , err ) )
2021-06-23 01:10:54 -05:00
}
// create a mc S3Client interface implementation
// defining the client to be used
mcClient := mcClient { client : s3Client }
parsedDate , errDate := time . Parse ( time . RFC3339 , params . Date )
if errDate != nil {
2022-04-28 12:55:06 -07:00
return nil , ErrorWithContext ( ctx , errDate )
2021-06-23 01:10:54 -05:00
}
var rewindItems [ ] * models . RewindItem
for content := range mcClient . client . List ( ctx , cmd . ListOptions { TimeRef : parsedDate , WithDeleteMarkers : true } ) {
// build object name
2022-05-05 13:44:10 -07:00
name := strings . ReplaceAll ( content . URL . Path , fmt . Sprintf ( "/%s/" , params . BucketName ) , "" )
2021-06-23 01:10:54 -05:00
listElement := & models . RewindItem {
LastModified : content . Time . Format ( time . RFC3339 ) ,
Size : content . Size ,
VersionID : content . VersionID ,
DeleteFlag : content . IsDeleteMarker ,
Action : "" ,
Name : name ,
}
rewindItems = append ( rewindItems , listElement )
}
return & models . RewindResponse {
Objects : rewindItems ,
} , nil
}