mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-31 17:28:12 +00:00
refactor(storage): inline acl entrypoints (#2501)
Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -23,7 +23,6 @@ use crate::error::ApiError;
|
|||||||
use crate::server::RemoteAddr;
|
use crate::server::RemoteAddr;
|
||||||
use crate::storage::access::{ReqInfo, authorize_request, req_info_ref};
|
use crate::storage::access::{ReqInfo, authorize_request, req_info_ref};
|
||||||
use crate::storage::helper::{OperationHelper, spawn_background_with_context};
|
use crate::storage::helper::{OperationHelper, spawn_background_with_context};
|
||||||
use crate::storage::s3_api::acl;
|
|
||||||
use crate::storage::s3_api::bucket::{
|
use crate::storage::s3_api::bucket::{
|
||||||
ListObjectVersionsParams, ListObjectsV2Params, build_list_buckets_output, build_list_object_versions_output,
|
ListObjectVersionsParams, ListObjectsV2Params, build_list_buckets_output, build_list_object_versions_output,
|
||||||
build_list_objects_output, build_list_objects_v2_output, parse_list_object_versions_params, parse_list_objects_v2_params,
|
build_list_objects_output, build_list_objects_v2_output, parse_list_object_versions_params, parse_list_objects_v2_params,
|
||||||
@@ -574,32 +573,6 @@ impl DefaultBucketUsecase {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_put_bucket_acl(&self, req: S3Request<PutBucketAclInput>) -> S3Result<S3Response<PutBucketAclOutput>> {
|
|
||||||
let PutBucketAclInput {
|
|
||||||
bucket,
|
|
||||||
access_control_policy,
|
|
||||||
..
|
|
||||||
} = req.input;
|
|
||||||
|
|
||||||
let Some(store) = new_object_layer_fn() else {
|
|
||||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
|
||||||
};
|
|
||||||
|
|
||||||
store
|
|
||||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
|
||||||
.await
|
|
||||||
.map_err(ApiError::from)?;
|
|
||||||
|
|
||||||
if access_control_policy.is_some() {
|
|
||||||
return Err(s3_error!(
|
|
||||||
NotImplemented,
|
|
||||||
"ACL XML grants are not supported; use canned ACL headers or omit ACL"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(S3Response::new(PutBucketAclOutput::default()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
pub async fn execute_delete_bucket(&self, mut req: S3Request<DeleteBucketInput>) -> S3Result<S3Response<DeleteBucketOutput>> {
|
pub async fn execute_delete_bucket(&self, mut req: S3Request<DeleteBucketInput>) -> S3Result<S3Response<DeleteBucketOutput>> {
|
||||||
let helper = OperationHelper::new(&req, EventName::BucketRemoved, S3Operation::DeleteBucket);
|
let helper = OperationHelper::new(&req, EventName::BucketRemoved, S3Operation::DeleteBucket);
|
||||||
@@ -655,21 +628,6 @@ impl DefaultBucketUsecase {
|
|||||||
Ok(S3Response::new(HeadBucketOutput::default()))
|
Ok(S3Response::new(HeadBucketOutput::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_get_bucket_acl(&self, req: S3Request<GetBucketAclInput>) -> S3Result<S3Response<GetBucketAclOutput>> {
|
|
||||||
let GetBucketAclInput { bucket, .. } = req.input;
|
|
||||||
|
|
||||||
let Some(store) = new_object_layer_fn() else {
|
|
||||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
|
||||||
};
|
|
||||||
|
|
||||||
store
|
|
||||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
|
||||||
.await
|
|
||||||
.map_err(ApiError::from)?;
|
|
||||||
|
|
||||||
Ok(S3Response::new(acl::build_get_bucket_acl_output()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
pub async fn execute_get_bucket_location(
|
pub async fn execute_get_bucket_location(
|
||||||
&self,
|
&self,
|
||||||
@@ -2050,20 +2008,6 @@ mod tests {
|
|||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn execute_get_bucket_acl_returns_internal_error_when_store_uninitialized() {
|
|
||||||
let input = GetBucketAclInput::builder()
|
|
||||||
.bucket("test-bucket".to_string())
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let req = build_request(input, Method::GET);
|
|
||||||
let usecase = DefaultBucketUsecase::without_context();
|
|
||||||
|
|
||||||
let err = usecase.execute_get_bucket_acl(req).await.unwrap_err();
|
|
||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn execute_get_bucket_location_returns_internal_error_when_store_uninitialized() {
|
async fn execute_get_bucket_location_returns_internal_error_when_store_uninitialized() {
|
||||||
let input = GetBucketLocationInput::builder()
|
let input = GetBucketLocationInput::builder()
|
||||||
@@ -2733,20 +2677,6 @@ mod tests {
|
|||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn execute_put_bucket_acl_returns_internal_error_when_store_uninitialized() {
|
|
||||||
let input = PutBucketAclInput::builder()
|
|
||||||
.bucket("test-bucket".to_string())
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let req = build_request(input, Method::PUT);
|
|
||||||
let usecase = DefaultBucketUsecase::without_context();
|
|
||||||
|
|
||||||
let err = usecase.execute_put_bucket_acl(req).await.unwrap_err();
|
|
||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn execute_put_bucket_encryption_returns_internal_error_when_store_uninitialized() {
|
async fn execute_put_bucket_encryption_returns_internal_error_when_store_uninitialized() {
|
||||||
let input = PutBucketEncryptionInput::builder()
|
let input = PutBucketEncryptionInput::builder()
|
||||||
|
|||||||
@@ -674,42 +674,6 @@ impl DefaultObjectUsecase {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_put_object_acl(&self, req: S3Request<PutObjectAclInput>) -> S3Result<S3Response<PutObjectAclOutput>> {
|
|
||||||
let mut helper = OperationHelper::new(&req, EventName::ObjectAclPut, S3Operation::PutObjectAcl);
|
|
||||||
let PutObjectAclInput {
|
|
||||||
bucket,
|
|
||||||
key,
|
|
||||||
access_control_policy,
|
|
||||||
version_id,
|
|
||||||
..
|
|
||||||
} = req.input.clone();
|
|
||||||
|
|
||||||
let Some(store) = new_object_layer_fn() else {
|
|
||||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
|
||||||
};
|
|
||||||
|
|
||||||
let opts: ObjectOptions = get_opts(&bucket, &key, version_id.clone(), None, &req.headers)
|
|
||||||
.await
|
|
||||||
.map_err(ApiError::from)?;
|
|
||||||
let object_info = store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
|
|
||||||
|
|
||||||
if access_control_policy.is_some() {
|
|
||||||
return Err(s3_error!(
|
|
||||||
NotImplemented,
|
|
||||||
"ACL XML grants are not supported; use canned ACL headers or omit ACL"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let event_version_id = version_id
|
|
||||||
.or_else(|| object_info.version_id.map(|version_id| version_id.to_string()))
|
|
||||||
.unwrap_or_default();
|
|
||||||
helper = helper.object(object_info).version_id(event_version_id);
|
|
||||||
|
|
||||||
let result = Ok(S3Response::new(PutObjectAclOutput::default()));
|
|
||||||
let _ = helper.complete(&result);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(
|
#[instrument(
|
||||||
level = "debug",
|
level = "debug",
|
||||||
skip(self, req),
|
skip(self, req),
|
||||||
@@ -2666,21 +2630,6 @@ mod tests {
|
|||||||
assert!(build_put_object_expiration_header(&event).is_none());
|
assert!(build_put_object_expiration_header(&event).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn execute_put_object_acl_returns_internal_error_when_store_uninitialized() {
|
|
||||||
let input = PutObjectAclInput::builder()
|
|
||||||
.bucket("test-bucket".to_string())
|
|
||||||
.key("test-key".to_string())
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let req = build_request(input, Method::PUT);
|
|
||||||
let usecase = DefaultObjectUsecase::without_context();
|
|
||||||
|
|
||||||
let err = usecase.execute_put_object_acl(req).await.unwrap_err();
|
|
||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn execute_head_object_rejects_range_with_part_number() {
|
async fn execute_head_object_rejects_range_with_part_number() {
|
||||||
let input = HeadObjectInput::builder()
|
let input = HeadObjectInput::builder()
|
||||||
|
|||||||
@@ -426,8 +426,18 @@ impl S3 for FS {
|
|||||||
|
|
||||||
async fn get_bucket_acl(&self, req: S3Request<GetBucketAclInput>) -> S3Result<S3Response<GetBucketAclOutput>> {
|
async fn get_bucket_acl(&self, req: S3Request<GetBucketAclInput>) -> S3Result<S3Response<GetBucketAclOutput>> {
|
||||||
record_s3_op(S3Operation::GetBucketAcl, &req.input.bucket);
|
record_s3_op(S3Operation::GetBucketAcl, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let GetBucketAclInput { bucket, .. } = req.input;
|
||||||
usecase.execute_get_bucket_acl(req).await
|
|
||||||
|
let Some(store) = new_object_layer_fn() else {
|
||||||
|
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
store
|
||||||
|
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||||
|
.await
|
||||||
|
.map_err(ApiError::from)?;
|
||||||
|
|
||||||
|
Ok(S3Response::new(acl::build_get_bucket_acl_output()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_bucket_accelerate_configuration(
|
async fn get_bucket_accelerate_configuration(
|
||||||
@@ -897,8 +907,30 @@ impl S3 for FS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn put_bucket_acl(&self, req: S3Request<PutBucketAclInput>) -> S3Result<S3Response<PutBucketAclOutput>> {
|
async fn put_bucket_acl(&self, req: S3Request<PutBucketAclInput>) -> S3Result<S3Response<PutBucketAclOutput>> {
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let PutBucketAclInput {
|
||||||
usecase.execute_put_bucket_acl(req).await
|
bucket,
|
||||||
|
access_control_policy,
|
||||||
|
..
|
||||||
|
} = req.input;
|
||||||
|
record_s3_op(S3Operation::PutBucketAcl, &bucket);
|
||||||
|
|
||||||
|
let Some(store) = new_object_layer_fn() else {
|
||||||
|
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
store
|
||||||
|
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||||
|
.await
|
||||||
|
.map_err(ApiError::from)?;
|
||||||
|
|
||||||
|
if access_control_policy.is_some() {
|
||||||
|
return Err(s3_error!(
|
||||||
|
NotImplemented,
|
||||||
|
"ACL XML grants are not supported; use canned ACL headers or omit ACL"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(S3Response::new(PutBucketAclOutput::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_bucket_accelerate_configuration(
|
async fn put_bucket_accelerate_configuration(
|
||||||
@@ -1075,8 +1107,35 @@ impl S3 for FS {
|
|||||||
|
|
||||||
async fn put_object_acl(&self, req: S3Request<PutObjectAclInput>) -> S3Result<S3Response<PutObjectAclOutput>> {
|
async fn put_object_acl(&self, req: S3Request<PutObjectAclInput>) -> S3Result<S3Response<PutObjectAclOutput>> {
|
||||||
record_s3_op(S3Operation::PutObjectAcl, &req.input.bucket);
|
record_s3_op(S3Operation::PutObjectAcl, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let mut helper = OperationHelper::new(&req, EventName::ObjectAclPut, S3Operation::PutObjectAcl);
|
||||||
usecase.execute_put_object_acl(req).await
|
let bucket = &req.input.bucket;
|
||||||
|
let key = &req.input.key;
|
||||||
|
let version_id = req.input.version_id.clone();
|
||||||
|
|
||||||
|
let Some(store) = new_object_layer_fn() else {
|
||||||
|
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
let opts: ObjectOptions = get_opts(bucket, key, version_id.clone(), None, &req.headers)
|
||||||
|
.await
|
||||||
|
.map_err(ApiError::from)?;
|
||||||
|
let object_info = store.get_object_info(bucket, key, &opts).await.map_err(ApiError::from)?;
|
||||||
|
|
||||||
|
if req.input.access_control_policy.is_some() {
|
||||||
|
return Err(s3_error!(
|
||||||
|
NotImplemented,
|
||||||
|
"ACL XML grants are not supported; use canned ACL headers or omit ACL"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let event_version_id = version_id
|
||||||
|
.or_else(|| object_info.version_id.map(|version_id| version_id.to_string()))
|
||||||
|
.unwrap_or_default();
|
||||||
|
helper = helper.object(object_info).version_id(event_version_id);
|
||||||
|
|
||||||
|
let result = Ok(S3Response::new(PutObjectAclOutput::default()));
|
||||||
|
let _ = helper.complete(&result);
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_object_legal_hold(
|
async fn put_object_legal_hold(
|
||||||
|
|||||||
@@ -35,11 +35,12 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use rustfs_zip::CompressionFormat;
|
use rustfs_zip::CompressionFormat;
|
||||||
use s3s::dto::{
|
use s3s::dto::{
|
||||||
CORSConfiguration, CORSRule, DefaultRetention, DeleteObjectTaggingInput, Delimiter, GetObjectAclInput,
|
CORSConfiguration, CORSRule, DefaultRetention, DeleteObjectTaggingInput, Delimiter, GetBucketAclInput, GetObjectAclInput,
|
||||||
GetObjectLegalHoldInput, GetObjectRetentionInput, GetObjectTaggingInput, LambdaFunctionConfiguration,
|
GetObjectLegalHoldInput, GetObjectRetentionInput, GetObjectTaggingInput, LambdaFunctionConfiguration,
|
||||||
ObjectLockConfiguration, ObjectLockEnabled, ObjectLockLegalHold, ObjectLockLegalHoldStatus, ObjectLockRetention,
|
ObjectLockConfiguration, ObjectLockEnabled, ObjectLockLegalHold, ObjectLockLegalHoldStatus, ObjectLockRetention,
|
||||||
ObjectLockRetentionMode, ObjectLockRule, PutObjectLegalHoldInput, PutObjectLockConfigurationInput,
|
ObjectLockRetentionMode, ObjectLockRule, PutBucketAclInput, PutObjectAclInput, PutObjectLegalHoldInput,
|
||||||
PutObjectRetentionInput, PutObjectTaggingInput, QueueConfiguration, Tag, Tagging, TopicConfiguration,
|
PutObjectLockConfigurationInput, PutObjectRetentionInput, PutObjectTaggingInput, QueueConfiguration, Tag, Tagging,
|
||||||
|
TopicConfiguration,
|
||||||
};
|
};
|
||||||
use s3s::{S3, S3Error, S3ErrorCode, S3Request, s3_error};
|
use s3s::{S3, S3Error, S3ErrorCode, S3Request, s3_error};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
@@ -200,6 +201,18 @@ mod tests {
|
|||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_bucket_acl_returns_internal_error_when_store_uninitialized() {
|
||||||
|
let input = GetBucketAclInput::builder()
|
||||||
|
.bucket("test-bucket".to_string())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fs = FS::new();
|
||||||
|
let err = fs.get_bucket_acl(build_request(input, Method::GET)).await.unwrap_err();
|
||||||
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_object_legal_hold_returns_internal_error_when_store_uninitialized() {
|
async fn test_get_object_legal_hold_returns_internal_error_when_store_uninitialized() {
|
||||||
let input = GetObjectLegalHoldInput::builder()
|
let input = GetObjectLegalHoldInput::builder()
|
||||||
@@ -239,6 +252,31 @@ mod tests {
|
|||||||
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_put_bucket_acl_returns_internal_error_when_store_uninitialized() {
|
||||||
|
let input = PutBucketAclInput::builder()
|
||||||
|
.bucket("test-bucket".to_string())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fs = FS::new();
|
||||||
|
let err = fs.put_bucket_acl(build_request(input, Method::PUT)).await.unwrap_err();
|
||||||
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_put_object_acl_returns_internal_error_when_store_uninitialized() {
|
||||||
|
let input = PutObjectAclInput::builder()
|
||||||
|
.bucket("test-bucket".to_string())
|
||||||
|
.key("test-key".to_string())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fs = FS::new();
|
||||||
|
let err = fs.put_object_acl(build_request(input, Method::PUT)).await.unwrap_err();
|
||||||
|
assert_eq!(err.code(), &S3ErrorCode::InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_put_object_retention_returns_internal_error_when_store_uninitialized() {
|
async fn test_put_object_retention_returns_internal_error_when_store_uninitialized() {
|
||||||
let input = PutObjectRetentionInput::builder()
|
let input = PutObjectRetentionInput::builder()
|
||||||
|
|||||||
Reference in New Issue
Block a user