[#719] Improve lock error handling

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2022-10-07 17:11:51 +03:00 committed by Alex Vanin
parent d6d6a09f0d
commit b3d96e6460
2 changed files with 24 additions and 6 deletions

View file

@ -877,13 +877,13 @@ var errorCodes = errorCodeMap{
ErrPastObjectLockRetainDate: { ErrPastObjectLockRetainDate: {
ErrCode: ErrPastObjectLockRetainDate, ErrCode: ErrPastObjectLockRetainDate,
Code: "InvalidRequest", Code: "InvalidRequest",
Description: "the retain until date must be in the future", Description: "The retain until date must be in the future",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrUnknownWORMModeDirective: { ErrUnknownWORMModeDirective: {
ErrCode: ErrUnknownWORMModeDirective, ErrCode: ErrUnknownWORMModeDirective,
Code: "InvalidRequest", Code: "InvalidRequest",
Description: "unknown wormMode directive", Description: "Unknown wormMode directive",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrObjectLockInvalidHeaders: { ErrObjectLockInvalidHeaders: {

View file

@ -332,18 +332,28 @@ func formObjectLock(bktInfo *data.BucketInfo, defaultConfig *data.ObjectLockConf
} }
mode := header.Get(api.AmzObjectLockMode) mode := header.Get(api.AmzObjectLockMode)
until := header.Get(api.AmzObjectLockRetainUntilDate)
if mode != "" && until == "" || mode == "" && until != "" {
return nil, apiErrors.GetAPIError(apiErrors.ErrObjectLockInvalidHeaders)
}
if mode != "" { if mode != "" {
if objectLock.Retention == nil { if objectLock.Retention == nil {
objectLock.Retention = &data.RetentionLock{} objectLock.Retention = &data.RetentionLock{}
} }
if mode != complianceMode && mode != governanceMode {
return nil, apiErrors.GetAPIError(apiErrors.ErrUnknownWORMModeDirective)
}
objectLock.Retention.IsCompliance = mode == complianceMode objectLock.Retention.IsCompliance = mode == complianceMode
} }
until := header.Get(api.AmzObjectLockRetainUntilDate)
if until != "" { if until != "" {
retentionDate, err := time.Parse(time.RFC3339, until) retentionDate, err := time.Parse(time.RFC3339, until)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid header %s: '%s'", api.AmzObjectLockRetainUntilDate, until) return nil, apiErrors.GetAPIError(apiErrors.ErrInvalidRetentionDate)
} }
if objectLock.Retention == nil { if objectLock.Retention == nil {
objectLock.Retention = &data.RetentionLock{} objectLock.Retention = &data.RetentionLock{}
@ -359,6 +369,10 @@ func formObjectLock(bktInfo *data.BucketInfo, defaultConfig *data.ObjectLockConf
} }
objectLock.Retention.ByPassedGovernance = bypass objectLock.Retention.ByPassedGovernance = bypass
} }
if objectLock.Retention.Until.Before(time.Now()) {
return nil, apiErrors.GetAPIError(apiErrors.ErrPastObjectLockRetainDate)
}
} }
return objectLock, nil return objectLock, nil
@ -372,12 +386,16 @@ func existLockHeaders(header http.Header) bool {
func formObjectLockFromRetention(retention *data.Retention, header http.Header) (*data.ObjectLock, error) { func formObjectLockFromRetention(retention *data.Retention, header http.Header) (*data.ObjectLock, error) {
if retention.Mode != governanceMode && retention.Mode != complianceMode { if retention.Mode != governanceMode && retention.Mode != complianceMode {
return nil, fmt.Errorf("invalid retention mode: %s", retention.Mode) return nil, apiErrors.GetAPIError(apiErrors.ErrMalformedXML)
} }
retentionDate, err := time.Parse(time.RFC3339, retention.RetainUntilDate) retentionDate, err := time.Parse(time.RFC3339, retention.RetainUntilDate)
if err != nil { if err != nil {
return nil, fmt.Errorf("couldn't parse retain until date: %s", retention.RetainUntilDate) return nil, apiErrors.GetAPIError(apiErrors.ErrMalformedXML)
}
if retentionDate.Before(time.Now()) {
return nil, apiErrors.GetAPIError(apiErrors.ErrPastObjectLockRetainDate)
} }
var bypass bool var bypass bool