Skip to main content

02_basic_crud_operations/
02_basic_crud_operations.rs

1//! Basic CRUD Operations
2//!
3//! This example demonstrates:
4//! - Creating multiple types of resources (users, groups, roles)
5//! - Updating resources
6//! - Deleting resources
7//! - Listing resources
8//!
9//! Scenario: Managing a small team with users, groups, and roles.
10//!
11//! Run with: `cargo run --example 02_basic_crud_operations`
12
13use wami::arn::{TenantPath, WamiArn};
14use wami::context::WamiContext;
15use wami::store::memory::InMemoryWamiStore;
16use wami::store::traits::{GroupStore, RoleStore, UserStore};
17use wami::wami::identity::group::builder::build_group;
18use wami::wami::identity::role::builder::build_role;
19use wami::wami::identity::user::builder::build_user;
20
21#[tokio::main]
22async fn main() -> Result<(), Box<dyn std::error::Error>> {
23    println!("=== Basic CRUD Operations ===\n");
24
25    let mut store = InMemoryWamiStore::default();
26
27    // Create a WamiContext for operations
28    let context = WamiContext::builder()
29        .instance_id("123456789012")
30        .tenant_path(TenantPath::single(0))
31        .caller_arn(
32            WamiArn::builder()
33                .service(wami::arn::Service::Iam)
34                .tenant_path(TenantPath::single(0))
35                .wami_instance("123456789012")
36                .resource("user", "admin")
37                .build()?,
38        )
39        .is_root(false)
40        .build()?;
41
42    // === CREATE Operations ===
43    println!("Step 1: Creating resources...\n");
44
45    // Create users
46    println!("Creating users...");
47    let alice = build_user("alice".to_string(), Some("/users/".to_string()), &context)?;
48    let bob = build_user("bob".to_string(), Some("/users/".to_string()), &context)?;
49    let charlie = build_user("charlie".to_string(), Some("/users/".to_string()), &context)?;
50
51    store.create_user(alice).await?;
52    store.create_user(bob).await?;
53    store.create_user(charlie).await?;
54    println!("✓ Created 3 users: alice, bob, charlie");
55
56    // Create groups
57    println!("\nCreating groups...");
58    let developers = build_group(
59        "developers".to_string(),
60        Some("/groups/".to_string()),
61        &context,
62    )?;
63    let admins = build_group("admins".to_string(), Some("/groups/".to_string()), &context)?;
64
65    store.create_group(developers).await?;
66    store.create_group(admins).await?;
67    println!("✓ Created 2 groups: developers, admins");
68
69    // Create roles
70    println!("\nCreating roles...");
71    let deploy_role = build_role(
72        "deploy-role".to_string(),
73        r#"{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"sts:AssumeRole"}]}"#.to_string(),
74        Some("/roles/".to_string()),
75        None,
76        None,
77        &context,
78    )?;
79
80    store.create_role(deploy_role).await?;
81    println!("✓ Created 1 role: deploy-role");
82
83    // === READ Operations ===
84    println!("\n\nStep 2: Reading resources...\n");
85
86    // List all users
87    let (users, _, _) = store.list_users(None, None).await?;
88    println!("✓ Found {} users:", users.len());
89    for user in &users {
90        println!("  - {}", user.user_name);
91    }
92
93    // Get specific user
94    let alice_retrieved = store.get_user("alice").await?;
95    if let Some(user) = alice_retrieved {
96        println!("\n✓ Retrieved user 'alice':");
97        println!("  - User ID: {}", user.user_id);
98        println!("  - Path: {}", user.path);
99        println!("  - ARN: {}", user.arn);
100    }
101
102    // List all groups
103    let (groups, _, _) = store.list_groups(None, None).await?;
104    println!("\n✓ Found {} groups:", groups.len());
105    for group in &groups {
106        println!("  - {}", group.group_name);
107    }
108
109    // === UPDATE Operations ===
110    println!("\n\nStep 3: Updating resources...\n");
111
112    // Update a user (change path)
113    let mut alice = store.get_user("alice").await?.unwrap();
114    let old_path = alice.path.clone();
115    alice.path = "/admin-users/".to_string();
116    store.update_user(alice).await?;
117    println!(
118        "✓ Updated alice's path from '{}' to '/admin-users/'",
119        old_path
120    );
121
122    // Verify update
123    let alice_updated = store.get_user("alice").await?.unwrap();
124    println!("  Verified: path is now '{}'", alice_updated.path);
125
126    // === DELETE Operations ===
127    println!("\n\nStep 4: Deleting resources...\n");
128
129    // Delete a user
130    store.delete_user("charlie").await?;
131    println!("✓ Deleted user 'charlie'");
132
133    // Verify deletion
134    let charlie_check = store.get_user("charlie").await?;
135    if charlie_check.is_none() {
136        println!("  Verified: charlie no longer exists");
137    }
138
139    // List users after deletion
140    let (users_after, _, _) = store.list_users(None, None).await?;
141    println!("\n✓ Remaining users: {}", users_after.len());
142    for user in &users_after {
143        println!("  - {}", user.user_name);
144    }
145
146    println!("\n✅ Example completed successfully!");
147    println!("Key takeaways:");
148    println!("- CRUD operations are straightforward with store traits");
149    println!("- List operations support pagination (not shown here)");
150    println!("- Updates require fetching the resource first");
151    println!("- Deletions are permanent (no soft delete by default)");
152
153    Ok(())
154}