api-object-legal-hold.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * MinIO Go Library for Amazon S3 Compatible Cloud Storage
  3. * Copyright 2020 MinIO, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package minio
  18. import (
  19. "bytes"
  20. "context"
  21. "encoding/xml"
  22. "fmt"
  23. "net/http"
  24. "net/url"
  25. "github.com/minio/minio-go/v7/pkg/s3utils"
  26. )
  27. // objectLegalHold - object legal hold specified in
  28. // https://docs.aws.amazon.com/AmazonS3/latest/API/archive-RESTObjectPUTLegalHold.html
  29. type objectLegalHold struct {
  30. XMLNS string `xml:"xmlns,attr,omitempty"`
  31. XMLName xml.Name `xml:"LegalHold"`
  32. Status LegalHoldStatus `xml:"Status,omitempty"`
  33. }
  34. // PutObjectLegalHoldOptions represents options specified by user for PutObjectLegalHold call
  35. type PutObjectLegalHoldOptions struct {
  36. VersionID string
  37. Status *LegalHoldStatus
  38. }
  39. // GetObjectLegalHoldOptions represents options specified by user for GetObjectLegalHold call
  40. type GetObjectLegalHoldOptions struct {
  41. VersionID string
  42. }
  43. // LegalHoldStatus - object legal hold status.
  44. type LegalHoldStatus string
  45. const (
  46. // LegalHoldEnabled indicates legal hold is enabled
  47. LegalHoldEnabled LegalHoldStatus = "ON"
  48. // LegalHoldDisabled indicates legal hold is disabled
  49. LegalHoldDisabled LegalHoldStatus = "OFF"
  50. )
  51. func (r LegalHoldStatus) String() string {
  52. return string(r)
  53. }
  54. // IsValid - check whether this legal hold status is valid or not.
  55. func (r LegalHoldStatus) IsValid() bool {
  56. return r == LegalHoldEnabled || r == LegalHoldDisabled
  57. }
  58. func newObjectLegalHold(status *LegalHoldStatus) (*objectLegalHold, error) {
  59. if status == nil {
  60. return nil, fmt.Errorf("Status not set")
  61. }
  62. if !status.IsValid() {
  63. return nil, fmt.Errorf("invalid legal hold status `%v`", status)
  64. }
  65. legalHold := &objectLegalHold{
  66. Status: *status,
  67. }
  68. return legalHold, nil
  69. }
  70. // PutObjectLegalHold : sets object legal hold for a given object and versionID.
  71. func (c Client) PutObjectLegalHold(ctx context.Context, bucketName, objectName string, opts PutObjectLegalHoldOptions) error {
  72. // Input validation.
  73. if err := s3utils.CheckValidBucketName(bucketName); err != nil {
  74. return err
  75. }
  76. if err := s3utils.CheckValidObjectName(objectName); err != nil {
  77. return err
  78. }
  79. // Get resources properly escaped and lined up before
  80. // using them in http request.
  81. urlValues := make(url.Values)
  82. urlValues.Set("legal-hold", "")
  83. if opts.VersionID != "" {
  84. urlValues.Set("versionId", opts.VersionID)
  85. }
  86. lh, err := newObjectLegalHold(opts.Status)
  87. if err != nil {
  88. return err
  89. }
  90. lhData, err := xml.Marshal(lh)
  91. if err != nil {
  92. return err
  93. }
  94. reqMetadata := requestMetadata{
  95. bucketName: bucketName,
  96. objectName: objectName,
  97. queryValues: urlValues,
  98. contentBody: bytes.NewReader(lhData),
  99. contentLength: int64(len(lhData)),
  100. contentMD5Base64: sumMD5Base64(lhData),
  101. contentSHA256Hex: sum256Hex(lhData),
  102. }
  103. // Execute PUT Object Legal Hold.
  104. resp, err := c.executeMethod(ctx, http.MethodPut, reqMetadata)
  105. defer closeResponse(resp)
  106. if err != nil {
  107. return err
  108. }
  109. if resp != nil {
  110. if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
  111. return httpRespToErrorResponse(resp, bucketName, objectName)
  112. }
  113. }
  114. return nil
  115. }
  116. // GetObjectLegalHold gets legal-hold status of given object.
  117. func (c Client) GetObjectLegalHold(ctx context.Context, bucketName, objectName string, opts GetObjectLegalHoldOptions) (status *LegalHoldStatus, err error) {
  118. // Input validation.
  119. if err := s3utils.CheckValidBucketName(bucketName); err != nil {
  120. return nil, err
  121. }
  122. if err := s3utils.CheckValidObjectName(objectName); err != nil {
  123. return nil, err
  124. }
  125. urlValues := make(url.Values)
  126. urlValues.Set("legal-hold", "")
  127. if opts.VersionID != "" {
  128. urlValues.Set("versionId", opts.VersionID)
  129. }
  130. // Execute GET on bucket to list objects.
  131. resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{
  132. bucketName: bucketName,
  133. objectName: objectName,
  134. queryValues: urlValues,
  135. contentSHA256Hex: emptySHA256Hex,
  136. })
  137. defer closeResponse(resp)
  138. if err != nil {
  139. return nil, err
  140. }
  141. if resp != nil {
  142. if resp.StatusCode != http.StatusOK {
  143. return nil, httpRespToErrorResponse(resp, bucketName, objectName)
  144. }
  145. }
  146. lh := &objectLegalHold{}
  147. if err = xml.NewDecoder(resp.Body).Decode(lh); err != nil {
  148. return nil, err
  149. }
  150. return &lh.Status, nil
  151. }