use scim_server::{
RequestContext, providers::StandardResourceProvider, resource::provider::ResourceProvider,
storage::InMemoryStorage,
};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("๐ Starting SCIM Server Basic Usage Example");
let storage = InMemoryStorage::new();
let provider = StandardResourceProvider::new(storage);
println!("โ
StandardResourceProvider initialized with in-memory storage");
let context = RequestContext::new("example-request-1".to_string());
println!("\n๐ Creating users...");
let user1_data = json!({
"userName": "john.doe@example.com",
"name": {
"formatted": "John Doe",
"familyName": "Doe",
"givenName": "John"
},
"emails": [
{
"value": "john.doe@example.com",
"type": "work",
"primary": true
},
{
"value": "john.personal@example.com",
"type": "home",
"primary": false
}
],
"phoneNumbers": [
{
"value": "+1-555-555-1234",
"type": "work"
}
],
"active": true
});
let user1 = provider
.create_resource("User", user1_data, &context)
.await?;
println!(
"โ
Created user: {} (ID: {})",
user1.get_username().unwrap_or("unknown"),
user1.get_id().unwrap_or("unknown")
);
let user2_data = json!({
"userName": "jane.smith@example.com",
"name": {
"formatted": "Jane Smith",
"familyName": "Smith",
"givenName": "Jane"
},
"emails": [
{
"value": "jane.smith@example.com",
"type": "work",
"primary": true
}
],
"active": true
});
let user2 = provider
.create_resource("User", user2_data, &context)
.await?;
println!(
"โ
Created user: {} (ID: {})",
user2.get_username().unwrap_or("unknown"),
user2.get_id().unwrap_or("unknown")
);
println!("\n๐ Listing all users...");
let users = provider.list_resources("User", None, &context).await?;
println!("๐ Found {} users:", users.len());
for user in &users {
println!(
" - {} ({})",
user.get_username().unwrap_or("unknown"),
user.get_id().unwrap_or("unknown")
);
}
println!("\n๐ Finding users by attributes...");
let found_user = provider
.find_resource_by_attribute("User", "userName", &json!("john.doe@example.com"), &context)
.await?;
match found_user {
Some(user) => {
println!(
"โ
Found user by username: {} (ID: {})",
user.get_username().unwrap_or("unknown"),
user.get_id().unwrap_or("unknown")
);
}
None => println!("โ User not found by username"),
}
let found_by_email = provider
.find_resource_by_attribute(
"User",
"emails.value",
&json!("jane.smith@example.com"),
&context,
)
.await?;
match found_by_email {
Some(user) => {
println!(
"โ
Found user by email: {} (ID: {})",
user.get_username().unwrap_or("unknown"),
user.get_id().unwrap_or("unknown")
);
}
None => println!("โ User not found by email"),
}
println!("\nโ๏ธ Updating user...");
let user1_id = user1.get_id().unwrap();
let updated_data = json!({
"id": user1_id,
"userName": "john.doe@example.com",
"name": {
"formatted": "John Updated Doe",
"familyName": "Doe",
"givenName": "John",
"middleName": "Updated"
},
"emails": [
{
"value": "john.doe@example.com",
"type": "work",
"primary": true
},
{
"value": "john.personal@example.com",
"type": "home",
"primary": false
}
],
"phoneNumbers": [
{
"value": "+1-555-555-1234",
"type": "work"
},
{
"value": "+1-555-555-5678",
"type": "mobile"
}
],
"active": true
});
let updated_user = provider
.update_resource("User", user1_id, updated_data, &context)
.await?;
println!(
"โ
Updated user: {} (ID: {})",
updated_user.get_username().unwrap_or("unknown"),
updated_user.get_id().unwrap_or("unknown")
);
if let Some(name) = updated_user.get_name() {
if let Some(formatted) = name.formatted.as_ref() {
println!(" ๐ New formatted name: {}", formatted);
}
}
println!("\n๐ Working with phone numbers...");
if let Some(phone_numbers) = updated_user.get_phone_numbers() {
println!("๐ฑ User has {} phone numbers:", phone_numbers.len());
for phone in phone_numbers {
let phone_type = phone.phone_type.as_ref().map_or("unknown", |v| v);
println!(" - {}: {}", phone_type, phone.value);
}
}
println!("\n๐ง Working with email addresses...");
if let Some(emails) = updated_user.get_emails() {
println!("๐ง User has {} email addresses:", emails.len());
for email in emails {
let email_type = email.email_type.as_ref().map_or("unknown", |v| v);
let is_primary = email.primary.unwrap_or(false);
println!(
" - {}: {} (primary: {})",
email_type, email.value, is_primary
);
}
}
println!("\n๐๏ธ Testing resource existence and deletion...");
let user2_id = user2.get_id().unwrap();
let exists = provider.resource_exists("User", user2_id, &context).await?;
println!("โ
User {} exists: {}", user2_id, exists);
provider.delete_resource("User", user2_id, &context).await?;
println!("โ
Deleted user");
let exists_after = provider.resource_exists("User", user2_id, &context).await?;
println!(
"โ
User {} exists after deletion: {}",
user2_id, exists_after
);
let users_after = provider.list_resources("User", None, &context).await?;
println!("๐ Users remaining after deletion: {}", users_after.len());
println!("\n๐ Provider statistics...");
let stats = provider.get_stats().await;
println!("๐ Provider Statistics:");
println!(" โข Total tenants: {}", stats.tenant_count);
println!(" โข Total resources: {}", stats.total_resources);
println!(" โข Resource types: {:?}", stats.resource_types);
println!(" โข Resource type count: {}", stats.resource_type_count);
println!("\n๐งน Testing clear functionality...");
provider.clear().await;
let stats_after_clear = provider.get_stats().await;
println!("๐ Statistics after clear:");
println!(" โข Total tenants: {}", stats_after_clear.tenant_count);
println!(
" โข Total resources: {}",
stats_after_clear.total_resources
);
println!("\nโ
Basic Usage Example Complete!");
println!("๐ Successfully demonstrated:");
println!(" โข Creating resources with StandardResourceProvider");
println!(" โข Listing and searching resources");
println!(" โข Updating and deleting resources");
println!(" โข Working with complex attributes (emails, phone numbers)");
println!(" โข Provider statistics and resource existence checks");
println!(" โข Clear functionality for testing");
Ok(())
}