diff --git a/rustfs/src/storage/s3_api/mod.rs b/rustfs/src/storage/s3_api/mod.rs index 156c28e44..b017011d5 100644 --- a/rustfs/src/storage/s3_api/mod.rs +++ b/rustfs/src/storage/s3_api/mod.rs @@ -24,16 +24,7 @@ pub(crate) mod bucket; pub(crate) mod common; pub(crate) mod encryption; pub(crate) mod multipart; -pub(crate) mod object_lock; -/// Object helper facade placeholder. -/// -/// Read-path helpers shared across storage components should live in neutral -/// modules (for example, `storage::readers`) and be consumed from there. -/// Object-specific extraction steps can be added here incrementally. -pub(crate) mod object {} pub(crate) mod replication; -pub(crate) mod response; pub(crate) mod restore; pub(crate) mod select; pub(crate) mod tagging; -pub(crate) mod validation {} diff --git a/rustfs/src/storage/s3_api/object_lock.rs b/rustfs/src/storage/s3_api/object_lock.rs deleted file mode 100644 index a997feb80..000000000 --- a/rustfs/src/storage/s3_api/object_lock.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use s3s::dto::{ - GetObjectLegalHoldOutput, GetObjectLockConfigurationOutput, GetObjectRetentionOutput, ObjectLockConfiguration, - ObjectLockLegalHold, ObjectLockLegalHoldStatus, ObjectLockRetention, ObjectLockRetentionMode, PutObjectLegalHoldOutput, - PutObjectRetentionOutput, RequestCharged, Timestamp, -}; - -pub(crate) fn build_get_object_legal_hold_output(legal_hold_status: Option) -> GetObjectLegalHoldOutput { - let status = legal_hold_status.unwrap_or_else(|| ObjectLockLegalHoldStatus::OFF.to_string()); - GetObjectLegalHoldOutput { - legal_hold: Some(ObjectLockLegalHold { - status: Some(ObjectLockLegalHoldStatus::from(status)), - }), - } -} - -pub(crate) fn build_get_object_lock_configuration_output( - object_lock_configuration: Option, -) -> GetObjectLockConfigurationOutput { - GetObjectLockConfigurationOutput { - object_lock_configuration, - } -} - -pub(crate) fn build_get_object_retention_output( - mode: Option, - retain_until_date: Option, -) -> GetObjectRetentionOutput { - GetObjectRetentionOutput { - retention: Some(ObjectLockRetention { mode, retain_until_date }), - } -} - -pub(crate) fn build_put_object_legal_hold_output() -> PutObjectLegalHoldOutput { - PutObjectLegalHoldOutput { - request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)), - } -} - -pub(crate) fn build_put_object_retention_output() -> PutObjectRetentionOutput { - PutObjectRetentionOutput { - request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)), - } -} - -#[cfg(test)] -mod tests { - use super::{ - build_get_object_legal_hold_output, build_get_object_lock_configuration_output, build_get_object_retention_output, - build_put_object_legal_hold_output, build_put_object_retention_output, - }; - use s3s::dto::{ - ObjectLockConfiguration, ObjectLockEnabled, ObjectLockLegalHoldStatus, ObjectLockRetentionMode, RequestCharged, - }; - use time::OffsetDateTime; - - #[test] - fn test_build_get_object_legal_hold_output_defaults_to_off_when_missing() { - let output = build_get_object_legal_hold_output(None); - let status = output - .legal_hold - .as_ref() - .and_then(|hold| hold.status.as_ref()) - .map(ObjectLockLegalHoldStatus::as_str); - assert_eq!(status, Some(ObjectLockLegalHoldStatus::OFF)); - } - - #[test] - fn test_build_get_object_legal_hold_output_uses_input_status() { - let output = build_get_object_legal_hold_output(Some(ObjectLockLegalHoldStatus::ON.to_string())); - let status = output - .legal_hold - .as_ref() - .and_then(|hold| hold.status.as_ref()) - .map(ObjectLockLegalHoldStatus::as_str); - assert_eq!(status, Some(ObjectLockLegalHoldStatus::ON)); - } - - #[test] - fn test_build_get_object_lock_configuration_output_preserves_field() { - let cfg = ObjectLockConfiguration { - object_lock_enabled: Some(ObjectLockEnabled::from_static(ObjectLockEnabled::ENABLED)), - ..Default::default() - }; - let output = build_get_object_lock_configuration_output(Some(cfg.clone())); - assert_eq!(output.object_lock_configuration, Some(cfg)); - } - - #[test] - fn test_build_get_object_retention_output_preserves_fields() { - let mode = Some(ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::GOVERNANCE)); - let retain_until_date = Some(OffsetDateTime::UNIX_EPOCH.into()); - let output = build_get_object_retention_output(mode.clone(), retain_until_date.clone()); - - let retention = output.retention.expect("retention should be present"); - assert_eq!(retention.mode, mode); - assert_eq!(retention.retain_until_date, retain_until_date); - } - - #[test] - fn test_build_put_object_legal_hold_output_sets_request_charged() { - let output = build_put_object_legal_hold_output(); - assert_eq!( - output.request_charged.as_ref().map(RequestCharged::as_str), - Some(RequestCharged::REQUESTER) - ); - } - - #[test] - fn test_build_put_object_retention_output_sets_request_charged() { - let output = build_put_object_retention_output(); - assert_eq!( - output.request_charged.as_ref().map(RequestCharged::as_str), - Some(RequestCharged::REQUESTER) - ); - } -} diff --git a/rustfs/src/storage/s3_api/response.rs b/rustfs/src/storage/s3_api/response.rs deleted file mode 100644 index 6da1f83ae..000000000 --- a/rustfs/src/storage/s3_api/response.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::error::ApiError; -use rustfs_ecstore::error::StorageError; -use s3s::{S3Error, S3ErrorCode, S3Response}; - -pub(crate) fn s3_response(output: T) -> S3Response { - S3Response::new(output) -} - -pub(crate) fn not_initialized_error() -> S3Error { - S3Error::with_message(S3ErrorCode::InternalError, "Not init") -} - -pub(crate) fn access_denied_error() -> S3Error { - S3Error::with_message(S3ErrorCode::AccessDenied, "Access Denied") -} - -pub(crate) fn map_abort_multipart_upload_error(err: StorageError) -> S3Error { - // For abort multipart upload, malformed upload IDs should be hidden as NoSuchUpload - // to match S3 API compatibility expectations. - if matches!(err, StorageError::MalformedUploadID(_)) { - return S3Error::new(S3ErrorCode::NoSuchUpload); - } - - ApiError::from(err).into() -} - -#[cfg(test)] -mod tests { - use super::{access_denied_error, map_abort_multipart_upload_error, not_initialized_error, s3_response}; - use rustfs_ecstore::error::StorageError; - use s3s::{S3ErrorCode, S3Response}; - - #[test] - fn test_s3_response_wraps_output() { - let response: S3Response = s3_response(7); - assert_eq!(response.output, 7); - } - - #[test] - fn test_not_initialized_error_shape() { - let err = not_initialized_error(); - assert_eq!(*err.code(), S3ErrorCode::InternalError); - assert_eq!(err.message(), Some("Not init")); - } - - #[test] - fn test_access_denied_error_shape() { - let err = access_denied_error(); - assert_eq!(*err.code(), S3ErrorCode::AccessDenied); - assert_eq!(err.message(), Some("Access Denied")); - } - - #[test] - fn test_map_abort_multipart_upload_error_for_malformed_id() { - let err = map_abort_multipart_upload_error(StorageError::MalformedUploadID("bad-id".to_string())); - assert_eq!(*err.code(), S3ErrorCode::NoSuchUpload); - } - - #[test] - fn test_map_abort_multipart_upload_error_for_unexpected_error() { - let err = map_abort_multipart_upload_error(StorageError::Unexpected); - assert_eq!(*err.code(), S3ErrorCode::InternalError); - } -}