refactor: Restructure project layout and clean up dependencies (#30)

This commit introduces a significant reorganization of the project structure to improve maintainability and clarity.

Key changes include:
- Adjusted the directory layout for a more logical module organization.
- Removed unused crate dependencies, reducing the overall project size and potentially speeding up build times.
- Updated import paths and configuration files to reflect the structural changes.
This commit is contained in:
houseme
2025-07-02 19:33:12 +08:00
committed by GitHub
parent 0be4264eb1
commit 5826396cd0
322 changed files with 977 additions and 1542 deletions
@@ -0,0 +1,30 @@
// 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.
pub mod objectlock;
pub mod objectlock_sys;
use s3s::dto::{ObjectLockConfiguration, ObjectLockEnabled};
pub trait ObjectLockApi {
fn enabled(&self) -> bool;
}
impl ObjectLockApi for ObjectLockConfiguration {
fn enabled(&self) -> bool {
self.object_lock_enabled
.as_ref()
.is_some_and(|v| v.as_str() == ObjectLockEnabled::ENABLED)
}
}
@@ -0,0 +1,94 @@
// 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 std::collections::HashMap;
use time::{OffsetDateTime, format_description};
use s3s::dto::{Date, ObjectLockLegalHold, ObjectLockLegalHoldStatus, ObjectLockRetention, ObjectLockRetentionMode};
use s3s::header::{X_AMZ_OBJECT_LOCK_LEGAL_HOLD, X_AMZ_OBJECT_LOCK_MODE, X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE};
const _ERR_MALFORMED_BUCKET_OBJECT_CONFIG: &str = "invalid bucket object lock config";
const _ERR_INVALID_RETENTION_DATE: &str = "date must be provided in ISO 8601 format";
const _ERR_PAST_OBJECTLOCK_RETAIN_DATE: &str = "the retain until date must be in the future";
const _ERR_UNKNOWN_WORMMODE_DIRECTIVE: &str = "unknown WORM mode directive";
const _ERR_OBJECTLOCK_MISSING_CONTENT_MD5: &str =
"content-MD5 HTTP header is required for Put Object requests with Object Lock parameters";
const _ERR_OBJECTLOCK_INVALID_HEADERS: &str =
"x-amz-object-lock-retain-until-date and x-amz-object-lock-mode must both be supplied";
const _ERR_MALFORMED_XML: &str = "the XML you provided was not well-formed or did not validate against our published schema";
pub fn utc_now_ntp() -> OffsetDateTime {
OffsetDateTime::now_utc()
}
pub fn get_object_retention_meta(meta: HashMap<String, String>) -> ObjectLockRetention {
let mut retain_until_date: Date = Date::from(OffsetDateTime::UNIX_EPOCH);
let mut mode_str = meta.get(X_AMZ_OBJECT_LOCK_MODE.as_str().to_lowercase().as_str());
if mode_str.is_none() {
mode_str = Some(&meta[X_AMZ_OBJECT_LOCK_MODE.as_str()]);
}
let mode = if let Some(mode_str) = mode_str {
parse_ret_mode(mode_str.as_str())
} else {
return ObjectLockRetention {
mode: None,
retain_until_date: None,
};
};
let mut till_str = meta.get(X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE.as_str().to_lowercase().as_str());
if till_str.is_none() {
till_str = Some(&meta[X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE.as_str()]);
}
if let Some(till_str) = till_str {
let t = OffsetDateTime::parse(till_str, &format_description::well_known::Iso8601::DEFAULT);
if t.is_err() {
retain_until_date = Date::from(t.expect("err")); //TODO: utc
}
}
ObjectLockRetention {
mode: Some(mode),
retain_until_date: Some(retain_until_date),
}
}
pub fn get_object_legalhold_meta(meta: HashMap<String, String>) -> ObjectLockLegalHold {
let mut hold_str = meta.get(X_AMZ_OBJECT_LOCK_LEGAL_HOLD.as_str().to_lowercase().as_str());
if hold_str.is_none() {
hold_str = Some(&meta[X_AMZ_OBJECT_LOCK_LEGAL_HOLD.as_str()]);
}
if let Some(hold_str) = hold_str {
return ObjectLockLegalHold {
status: Some(parse_legalhold_status(hold_str)),
};
}
ObjectLockLegalHold { status: None }
}
pub fn parse_ret_mode(mode_str: &str) -> ObjectLockRetentionMode {
match mode_str.to_uppercase().as_str() {
"GOVERNANCE" => ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::GOVERNANCE),
"COMPLIANCE" => ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::COMPLIANCE),
_ => unreachable!(),
}
}
pub fn parse_legalhold_status(hold_str: &str) -> ObjectLockLegalHoldStatus {
match hold_str {
"ON" => ObjectLockLegalHoldStatus::from_static(ObjectLockLegalHoldStatus::ON),
"OFF" => ObjectLockLegalHoldStatus::from_static(ObjectLockLegalHoldStatus::OFF),
_ => unreachable!(),
}
}
@@ -0,0 +1,67 @@
// 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 std::sync::Arc;
use time::OffsetDateTime;
use s3s::dto::{DefaultRetention, ObjectLockLegalHoldStatus, ObjectLockRetentionMode};
use crate::bucket::metadata_sys::get_object_lock_config;
use crate::store_api::ObjectInfo;
use super::objectlock;
pub struct BucketObjectLockSys {}
impl BucketObjectLockSys {
#[allow(clippy::new_ret_no_self)]
pub async fn new() -> Arc<Self> {
Arc::new(Self {})
}
pub async fn get(bucket: &str) -> Option<DefaultRetention> {
if let Ok(object_lock_config) = get_object_lock_config(bucket).await {
if let Some(object_lock_rule) = object_lock_config.0.rule {
return object_lock_rule.default_retention;
}
}
None
}
}
pub fn enforce_retention_for_deletion(obj_info: &ObjectInfo) -> bool {
if obj_info.delete_marker {
return false;
}
let lhold = objectlock::get_object_legalhold_meta(obj_info.user_defined.clone());
match lhold.status {
Some(st) if st.as_str() == ObjectLockLegalHoldStatus::ON => {
return true;
}
_ => (),
}
let ret = objectlock::get_object_retention_meta(obj_info.user_defined.clone());
match ret.mode {
Some(r) if (r.as_str() == ObjectLockRetentionMode::COMPLIANCE || r.as_str() == ObjectLockRetentionMode::GOVERNANCE) => {
let t = objectlock::utc_now_ntp();
if OffsetDateTime::from(ret.retain_until_date.expect("err!")).unix_timestamp() > t.unix_timestamp() {
return true;
}
}
_ => (),
}
false
}