use std::sync::{Arc, RwLock};
use wami::provider::AwsProvider;
use wami::service::{TenantService, UserService};
use wami::store::memory::InMemoryWamiStore;
use wami::wami::identity::user::requests::{CreateUserRequest, ListUsersRequest};
use wami::wami::tenant::model::TenantId;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Simple Multi-Tenant Setup ===\n");
let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
let _provider = Arc::new(AwsProvider::new());
println!("Step 1: Creating tenants...\n");
let tenant_service = TenantService::new(store.clone(), "root".to_string());
let _company_a_id = TenantId::new("company-a");
tenant_service
.create_tenant(
"company-a".to_string(),
Some("Company A Corp".to_string()),
None, )
.await?;
println!("✓ Created tenant: company-a");
let _company_b_id = TenantId::new("company-b");
tenant_service
.create_tenant(
"company-b".to_string(),
Some("Company B Inc".to_string()),
None,
)
.await?;
println!("✓ Created tenant: company-b");
println!("\nStep 2: Creating users in each tenant...\n");
println!("Creating users for Company A...");
let user_service_a = UserService::new(
store.clone(),
"company-a".to_string(), );
let alice_req = CreateUserRequest {
user_name: "alice".to_string(),
path: Some("/company-a/".to_string()),
permissions_boundary: None,
tags: None,
};
let alice = user_service_a.create_user(alice_req).await?;
println!("✓ Created alice in company-a");
println!(" ARN: {}", alice.arn);
let bob_req = CreateUserRequest {
user_name: "bob".to_string(),
path: Some("/company-a/".to_string()),
permissions_boundary: None,
tags: None,
};
user_service_a.create_user(bob_req).await?;
println!("✓ Created bob in company-a");
println!("\nCreating users for Company B...");
let user_service_b = UserService::new(
store.clone(),
"company-b".to_string(), );
let charlie_req = CreateUserRequest {
user_name: "charlie".to_string(),
path: Some("/company-b/".to_string()),
permissions_boundary: None,
tags: None,
};
let charlie = user_service_b.create_user(charlie_req).await?;
println!("✓ Created charlie in company-b");
println!(" ARN: {}", charlie.arn);
let diana_req = CreateUserRequest {
user_name: "diana".to_string(),
path: Some("/company-b/".to_string()),
permissions_boundary: None,
tags: None,
};
user_service_b.create_user(diana_req).await?;
println!("✓ Created diana in company-b");
println!("\n\nStep 3: Demonstrating tenant isolation...\n");
let all_users_service = UserService::new(store.clone(), "root".to_string());
let (all_users, _, _) = all_users_service
.list_users(ListUsersRequest {
path_prefix: None,
pagination: None,
})
.await?;
println!("Total users across all tenants: {}", all_users.len());
let (company_a_users, _, _) = user_service_a
.list_users(ListUsersRequest {
path_prefix: None,
pagination: None,
})
.await?;
println!(
"\nCompany A users (via company-a service): {}",
company_a_users.len()
);
for user in &company_a_users {
println!(" - {} (path: {})", user.user_name, user.path);
}
let (company_b_users, _, _) = user_service_b
.list_users(ListUsersRequest {
path_prefix: None,
pagination: None,
})
.await?;
println!(
"\nCompany B users (via company-b service): {}",
company_b_users.len()
);
for user in &company_b_users {
println!(" - {} (path: {})", user.user_name, user.path);
}
println!("\n\nStep 4: Listing all tenants...\n");
let all_tenants = tenant_service.list_tenants().await?;
println!("✓ Found {} tenants:", all_tenants.len());
for tenant in &all_tenants {
println!(" - {} ({})", tenant.name, tenant.id);
}
println!("\n✅ Example completed successfully!");
println!("Key takeaways:");
println!("- Each tenant has its own namespace for resources");
println!("- Services can be scoped to specific tenants via account_id");
println!("- ARNs reflect the tenant/account ownership");
println!("- Tenant isolation ensures data security in multi-tenant apps");
Ok(())
}