aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchrislu <chris.lu@gmail.com>2025-07-18 16:38:24 -0700
committerchrislu <chris.lu@gmail.com>2025-07-18 16:38:24 -0700
commitf419271299fffd3fecd95e67caedd23039d6ad3c (patch)
treece7059f4b73404a97f89f941321bb79e57345e4f
parenta0ab227e078987bf81551ff80586324fba6c7083 (diff)
downloadseaweedfs-f419271299fffd3fecd95e67caedd23039d6ad3c.tar.xz
seaweedfs-f419271299fffd3fecd95e67caedd23039d6ad3c.zip
pass tests
-rw-r--r--weed/s3api/s3api_object_handlers_put.go4
-rw-r--r--weed/s3api/s3api_object_retention.go39
2 files changed, 29 insertions, 14 deletions
diff --git a/weed/s3api/s3api_object_handlers_put.go b/weed/s3api/s3api_object_handlers_put.go
index 99ad5d9ed..b534f9662 100644
--- a/weed/s3api/s3api_object_handlers_put.go
+++ b/weed/s3api/s3api_object_handlers_put.go
@@ -596,6 +596,10 @@ func mapValidationErrorToS3Error(err error) s3err.ErrorCode {
// For governance bypass on non-versioned bucket, return InvalidRequest
// This matches the test expectations
return s3err.ErrInvalidRequest
+ case errors.Is(err, ErrMalformedXML):
+ // For malformed XML in request body, return MalformedXML
+ // This matches the test expectations for invalid retention mode and legal hold status
+ return s3err.ErrMalformedXML
// Validation error constants
case errors.Is(err, ErrObjectLockConfigurationMissingEnabled):
return s3err.ErrMalformedXML
diff --git a/weed/s3api/s3api_object_retention.go b/weed/s3api/s3api_object_retention.go
index d69a5f857..ca4c38a27 100644
--- a/weed/s3api/s3api_object_retention.go
+++ b/weed/s3api/s3api_object_retention.go
@@ -34,6 +34,7 @@ var (
ErrInvalidRetentionPeriod = errors.New("invalid retention period specified")
ErrInvalidRetentionMode = errors.New("invalid retention mode specified")
ErrBothDaysAndYearsSpecified = errors.New("both days and years cannot be specified in the same retention configuration")
+ ErrMalformedXML = errors.New("malformed XML in request body")
)
const (
@@ -165,8 +166,10 @@ func validateRetention(retention *ObjectRetention) error {
return ErrInvalidRetentionPeriod
}
+ // For invalid retention mode values, return MalformedXML error
+ // This matches the test expectations for lowercase/invalid mode values
if retention.Mode != s3_constants.RetentionModeGovernance && retention.Mode != s3_constants.RetentionModeCompliance {
- return ErrInvalidRetentionMode
+ return ErrMalformedXML
}
if retention.RetainUntilDate.Before(time.Now()) {
@@ -178,8 +181,10 @@ func validateRetention(retention *ObjectRetention) error {
// validateLegalHold validates legal hold configuration
func validateLegalHold(legalHold *ObjectLegalHold) error {
+ // For invalid legal hold status values, return MalformedXML error
+ // This matches the test expectations for invalid status values
if legalHold.Status != s3_constants.LegalHoldOn && legalHold.Status != s3_constants.LegalHoldOff {
- return ErrInvalidLegalHoldStatus
+ return ErrMalformedXML
}
return nil
@@ -230,8 +235,12 @@ func validateDefaultRetention(retention *DefaultRetention) error {
return ErrDefaultRetentionBothDaysAndYears
}
- // Validate ranges
- if retention.Days < 0 || retention.Days > MaxRetentionDays {
+ // Validate ranges - Days must be greater than 0
+ if retention.Days <= 0 {
+ return ErrInvalidRetentionPeriod
+ }
+
+ if retention.Days > MaxRetentionDays {
return ErrDefaultRetentionDaysOutOfRange
}
@@ -599,17 +608,19 @@ func (s3a *S3ApiServer) checkGovernanceBypassPermission(request *http.Request, b
// checkObjectLockPermissions checks if an object can be deleted or modified
func (s3a *S3ApiServer) checkObjectLockPermissions(request *http.Request, bucket, object, versionId string, bypassGovernance bool) error {
- // For delete operations without versionId (which create delete markers),
- // we should allow the operation even if the object is under retention.
- // This is because delete markers are logical deletes, not physical deletes.
- // Only block deletions when a specific versionId is provided.
- if versionId == "" {
- // This is a delete marker creation - allow it
- return nil
+ // Get the object entry to check both retention and legal hold
+ // For delete operations without versionId, we need to check the latest version
+ var entry *filer_pb.Entry
+ var err error
+
+ if versionId != "" {
+ // Check specific version
+ entry, err = s3a.getObjectEntry(bucket, object, versionId)
+ } else {
+ // Check latest version for delete marker creation
+ entry, err = s3a.getObjectEntry(bucket, object, "")
}
- // Get the object entry once to check both retention and legal hold
- entry, err := s3a.getObjectEntry(bucket, object, versionId)
if err != nil {
// If object doesn't exist, it's not under retention or legal hold - this is expected during delete operations
if errors.Is(err, ErrObjectNotFound) || errors.Is(err, ErrVersionNotFound) || errors.Is(err, ErrLatestVersionNotFound) {
@@ -635,7 +646,7 @@ func (s3a *S3ApiServer) checkObjectLockPermissions(request *http.Request, bucket
// Continue with retention check even if legal hold parsing fails
}
- // If object is under legal hold, it cannot be deleted or modified
+ // If object is under legal hold, it cannot be deleted or modified (including delete marker creation)
if legalHoldActive {
return ErrObjectUnderLegalHold
}