Files
cloudlysis/control/api/tests/s3_docs_gated.rs
Vlad Durnea 2595e7f1c5
Some checks failed
ci / ui (push) Failing after 28s
ci / rust (push) Failing after 2m40s
images / build-and-push (push) Failing after 19s
feat(billing): implement tenant subscription entitlements system (milestones 0-6)
2026-03-30 18:41:23 +03:00

117 lines
3.2 KiB
Rust

use api::s3_docs::{DocsConfig, DocsStore};
use uuid::Uuid;
fn s3_env_ready() -> bool {
// Gate integration tests without requiring `-- --ignored`.
// If CI/local wants these tests to run, it must provide S3 env vars.
let required = [
"CONTROL_S3_ENDPOINT",
"CONTROL_S3_ACCESS_KEY_ID",
"CONTROL_S3_SECRET_ACCESS_KEY",
"CONTROL_S3_BUCKET_DOCS",
];
required
.iter()
.all(|k| std::env::var(k).ok().is_some_and(|v| !v.trim().is_empty()))
}
#[tokio::test]
async fn s3_docs_roundtrip_put_get_list_delete() {
if !s3_env_ready() {
eprintln!("skipping: missing S3 env (see S3_PLAN.md)");
return;
}
let cfg = DocsConfig::from_env().expect("missing S3 env (see S3_PLAN.md)");
let store = DocsStore::new(cfg)
.await
.expect("failed to init docs store");
let tenant_id = Uuid::new_v4().to_string();
let doc_type = "test";
let doc_id = Uuid::new_v4().to_string();
let filename = "hello.txt";
let key = store
.key_for(&tenant_id, doc_type, &doc_id, filename)
.expect("invalid key");
store
.put_for_tenant(
&tenant_id,
&key,
b"hello".to_vec(),
Some("text/plain".to_string()),
)
.await
.expect("put failed");
let (bytes, _ct) = store
.get_bytes_for_tenant(&tenant_id, &key)
.await
.expect("get failed");
assert_eq!(bytes, b"hello");
let prefix = format!("{}{}", store.prefix(), tenant_id);
let objects = store
.list_for_tenant(&tenant_id, &format!("{prefix}/"))
.await
.expect("list failed");
assert!(objects.iter().any(|o| o.key == key));
store
.delete_for_tenant(&tenant_id, &key)
.await
.expect("delete failed");
}
#[tokio::test]
async fn s3_docs_tenant_prefix_isolation() {
if !s3_env_ready() {
eprintln!("skipping: missing S3 env (see S3_PLAN.md)");
return;
}
let cfg = DocsConfig::from_env().expect("missing S3 env (see S3_PLAN.md)");
let store = DocsStore::new(cfg)
.await
.expect("failed to init docs store");
let tenant_a = Uuid::new_v4().to_string();
let tenant_b = Uuid::new_v4().to_string();
let doc_type = "test";
let doc_id = Uuid::new_v4().to_string();
let filename = "hello.txt";
let key_a = store
.key_for(&tenant_a, doc_type, &doc_id, filename)
.expect("invalid key");
store
.put_for_tenant(
&tenant_a,
&key_a,
b"hello-a".to_vec(),
Some("text/plain".to_string()),
)
.await
.expect("put failed");
let prefix_a = format!("{}{tenant_a}/", store.prefix());
let prefix_b = format!("{}{tenant_b}/", store.prefix());
let objects_a = store
.list_for_tenant(&tenant_a, &prefix_a)
.await
.expect("list a failed");
let objects_b = store
.list_for_tenant(&tenant_b, &prefix_b)
.await
.expect("list b failed");
assert!(objects_a.iter().any(|o| o.key == key_a));
assert!(!objects_b.iter().any(|o| o.key == key_a));
store
.delete_for_tenant(&tenant_a, &key_a)
.await
.expect("delete failed");
}