Skip to content

Commit f91346d

Browse files
cesnietordvaldivia
andauthored
Add retention mode and legal hold mode on list objects api (#312)
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
1 parent dccdfb5 commit f91346d

File tree

8 files changed

+442
-35
lines changed

8 files changed

+442
-35
lines changed

models/bucket_object.go

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

restapi/client.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"strings"
23+
"time"
2324

2425
"github.com/minio/minio-go/v7/pkg/replication"
2526

@@ -54,6 +55,8 @@ type MinioClient interface {
5455
getBucketNotification(ctx context.Context, bucketName string) (config notification.Configuration, err error)
5556
getBucketPolicy(ctx context.Context, bucketName string) (string, error)
5657
listObjects(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
58+
getObjectRetention(ctx context.Context, bucketName, objectName, versionID string) (mode *minio.RetentionMode, retainUntilDate *time.Time, err error)
59+
getObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.GetObjectLegalHoldOptions) (status *minio.LegalHoldStatus, err error)
5760
}
5861

5962
// Interface implementation
@@ -116,6 +119,14 @@ func (c minioClient) listObjects(ctx context.Context, bucket string, opts minio.
116119
return c.client.ListObjects(ctx, bucket, opts)
117120
}
118121

122+
func (c minioClient) getObjectRetention(ctx context.Context, bucketName, objectName, versionID string) (mode *minio.RetentionMode, retainUntilDate *time.Time, err error) {
123+
return c.client.GetObjectRetention(ctx, bucketName, objectName, versionID)
124+
}
125+
126+
func (c minioClient) getObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.GetObjectLegalHoldOptions) (status *minio.LegalHoldStatus, err error) {
127+
return c.client.GetObjectLegalHold(ctx, bucketName, objectName, opts)
128+
}
129+
119130
// MCClient interface with all functions to be implemented
120131
// by mock when testing, it should include all mc/S3Client respective api calls
121132
// that are used within this project.

restapi/embedded_spec.go

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

restapi/operations/user_api/list_objects_parameters.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

restapi/operations/user_api/list_objects_urlbuilder.go

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

restapi/user_objects.go

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package restapi
1919
import (
2020
"context"
2121
"fmt"
22+
"log"
2223
"path/filepath"
2324
"regexp"
2425
"strings"
@@ -29,6 +30,7 @@ import (
2930
"github.com/minio/console/restapi/operations"
3031
"github.com/minio/console/restapi/operations/user_api"
3132
mc "github.com/minio/mc/cmd"
33+
"github.com/minio/mc/pkg/probe"
3234
"github.com/minio/minio-go/v7"
3335
)
3436

@@ -62,12 +64,16 @@ func getListObjectsResponse(session *models.Principal, params user_api.ListObjec
6264
defer cancel()
6365
var prefix string
6466
var recursive bool
67+
var withVersions bool
6568
if params.Prefix != nil {
6669
prefix = *params.Prefix
6770
}
6871
if params.Recursive != nil {
6972
recursive = *params.Recursive
7073
}
74+
if params.WithVersions != nil {
75+
withVersions = *params.WithVersions
76+
}
7177
// bucket request needed to proceed
7278
if params.BucketName == "" {
7379
return nil, prepareError(errBucketNameNotInRequest)
@@ -80,7 +86,7 @@ func getListObjectsResponse(session *models.Principal, params user_api.ListObjec
8086
// defining the client to be used
8187
minioClient := minioClient{client: mClient}
8288

83-
objs, err := listBucketObjects(ctx, minioClient, params.BucketName, prefix, recursive)
89+
objs, err := listBucketObjects(ctx, minioClient, params.BucketName, prefix, recursive, withVersions)
8490
if err != nil {
8591
return nil, prepareError(err)
8692
}
@@ -93,17 +99,50 @@ func getListObjectsResponse(session *models.Principal, params user_api.ListObjec
9399
}
94100

95101
// listBucketObjects gets an array of objects in a bucket
96-
func listBucketObjects(ctx context.Context, client MinioClient, bucketName string, prefix string, recursive bool) ([]*models.BucketObject, error) {
102+
func listBucketObjects(ctx context.Context, client MinioClient, bucketName string, prefix string, recursive, withVersions bool) ([]*models.BucketObject, error) {
97103
var objects []*models.BucketObject
98-
for lsObj := range client.listObjects(ctx, bucketName, minio.ListObjectsOptions{Prefix: prefix, Recursive: recursive}) {
104+
for lsObj := range client.listObjects(ctx, bucketName, minio.ListObjectsOptions{Prefix: prefix, Recursive: recursive, WithVersions: withVersions}) {
99105
if lsObj.Err != nil {
100106
return nil, lsObj.Err
101107
}
102108
obj := &models.BucketObject{
103-
Name: lsObj.Key,
104-
Size: lsObj.Size,
105-
LastModified: lsObj.LastModified.String(),
106-
ContentType: lsObj.ContentType,
109+
Name: lsObj.Key,
110+
Size: lsObj.Size,
111+
LastModified: lsObj.LastModified.String(),
112+
ContentType: lsObj.ContentType,
113+
VersionID: lsObj.VersionID,
114+
IsLatest: lsObj.IsLatest,
115+
IsDeleteMarker: lsObj.IsDeleteMarker,
116+
UserTags: lsObj.UserTags,
117+
}
118+
if !lsObj.IsDeleteMarker {
119+
// Add Legal Hold Status if available
120+
legalHoldStatus, err := client.getObjectLegalHold(ctx, bucketName, lsObj.Key, minio.GetObjectLegalHoldOptions{VersionID: lsObj.VersionID})
121+
if err != nil {
122+
errResp := minio.ToErrorResponse(probe.NewError(err).ToGoError())
123+
if errResp.Code != "NoSuchObjectLockConfiguration" {
124+
log.Printf("error getting legal hold status for %s : %s", lsObj.VersionID, err)
125+
}
126+
127+
} else {
128+
if legalHoldStatus != nil {
129+
obj.LegalHoldStatus = string(*legalHoldStatus)
130+
}
131+
}
132+
// Add Retention Status if available
133+
retention, retUntilDate, err := client.getObjectRetention(ctx, bucketName, lsObj.Key, lsObj.VersionID)
134+
if err != nil {
135+
errResp := minio.ToErrorResponse(probe.NewError(err).ToGoError())
136+
if errResp.Code != "NoSuchObjectLockConfiguration" {
137+
log.Printf("error getting retention status for %s : %s", lsObj.VersionID, err)
138+
}
139+
} else {
140+
if retention != nil && retUntilDate != nil {
141+
date := *retUntilDate
142+
obj.RetentionMode = string(*retention)
143+
obj.RetentionUntilDate = date.String()
144+
}
145+
}
107146
}
108147
objects = append(objects, obj)
109148
}

0 commit comments

Comments
 (0)