03_service_layer_intro/
03_service_layer_intro.rs1use std::sync::Arc;
13use tokio::sync::RwLock;
14use wami::arn::{TenantPath, WamiArn};
15use wami::context::WamiContext;
16use wami::service::{GroupService, RoleService, UserService};
17use wami::store::memory::InMemoryWamiStore;
18use wami::wami::identity::group::requests::CreateGroupRequest;
19use wami::wami::identity::role::requests::CreateRoleRequest;
20use wami::wami::identity::user::requests::{CreateUserRequest, ListUsersRequest};
21
22#[tokio::main]
23async fn main() -> Result<(), Box<dyn std::error::Error>> {
24 println!("=== Service Layer Introduction ===\n");
25
26 println!("Step 1: Initializing services...\n");
28 let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
29
30 let context = WamiContext::builder()
32 .instance_id("123456789012")
33 .tenant_path(TenantPath::single(0))
34 .caller_arn(
35 WamiArn::builder()
36 .service(wami::arn::Service::Iam)
37 .tenant_path(TenantPath::single(0))
38 .wami_instance("123456789012")
39 .resource("user", "admin")
40 .build()?,
41 )
42 .is_root(false)
43 .build()?;
44
45 let user_service = UserService::new(store.clone());
47 let group_service = GroupService::new(store.clone());
48 let role_service = RoleService::new(store.clone());
49
50 println!("✓ Services initialized");
51
52 println!("\nStep 2: Creating resources via services...\n");
54
55 println!("Creating users...");
57 let alice_req = CreateUserRequest {
58 user_name: "alice".to_string(),
59 path: Some("/users/".to_string()),
60 permissions_boundary: None,
61 tags: None,
62 };
63 let alice = user_service.create_user(&context, alice_req).await?;
64 println!("✓ Created user: {}", alice.user_name);
65
66 let bob_req = CreateUserRequest {
67 user_name: "bob".to_string(),
68 path: Some("/users/".to_string()),
69 permissions_boundary: None,
70 tags: None,
71 };
72 user_service.create_user(&context, bob_req).await?;
73 println!("✓ Created user: bob");
74
75 println!("\nCreating groups...");
77 let dev_group_req = CreateGroupRequest {
78 group_name: "developers".to_string(),
79 path: Some("/groups/".to_string()),
80 tags: None,
81 };
82 let dev_group = group_service.create_group(&context, dev_group_req).await?;
83 println!("✓ Created group: {}", dev_group.group_name);
84
85 println!("\nCreating role...");
87 let role_req = CreateRoleRequest {
88 role_name: "deploy-role".to_string(),
89 path: Some("/roles/".to_string()),
90 assume_role_policy_document: r#"{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"sts:AssumeRole"}]}"#.to_string(),
91 description: Some("Role for deployment".to_string()),
92 max_session_duration: Some(3600),
93 permissions_boundary: None,
94 tags: None,
95 };
96 let role = role_service.create_role(&context, role_req).await?;
97 println!("✓ Created role: {}", role.role_name);
98
99 println!("\n\nStep 3: Reading resources via services...\n");
101
102 let alice_retrieved = user_service.get_user(&context, "alice").await?;
104 if let Some(user) = alice_retrieved {
105 println!("✓ Retrieved user 'alice':");
106 println!(" - User ID: {}", user.user_id);
107 println!(" - ARN: {}", user.arn);
108 }
109
110 let users = user_service
112 .list_users(
113 &context,
114 ListUsersRequest {
115 path_prefix: None,
116 pagination: None,
117 },
118 )
119 .await?;
120 println!("\n✓ Found {} users via service:", users.0.len());
121 for user in &users.0 {
122 println!(" - {}", user.user_name);
123 }
124
125 println!("\n\nStep 4: Updating resources via services...\n");
127
128 use wami::wami::identity::user::requests::UpdateUserRequest;
129 let update_req = UpdateUserRequest {
130 user_name: "alice".to_string(),
131 new_user_name: None,
132 new_path: Some("/admin-users/".to_string()),
133 };
134 user_service.update_user(&context, update_req).await?;
135 println!("✓ Updated alice's path to '/admin-users/'");
136
137 println!("\n\nStep 5: Deleting resources via services...\n");
139
140 user_service.delete_user(&context, "bob").await?;
141 println!("✓ Deleted user 'bob'");
142
143 let bob_check = user_service.get_user(&context, "bob").await?;
145 if bob_check.is_none() {
146 println!(" Verified: bob no longer exists");
147 }
148
149 println!("\n✅ Example completed successfully!");
150 println!("Key takeaways:");
151 println!("- Services provide a higher-level API than raw store access");
152 println!("- Arc<RwLock<Store>> enables thread-safe concurrent operations");
153 println!("- Services use request/response DTOs for clean API contracts");
154 println!("- Services encapsulate business logic and validation");
155
156 Ok(())
157}