hero/interfaces/websocket/server/examples/circle_auth_demo.rs
2025-07-30 08:36:55 +02:00

74 lines
3.2 KiB
Rust

use std::collections::HashMap;
use hero_websocket_server::ServerBuilder;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
// Define circles and their members
let mut circles = HashMap::new();
// Circle "alpha" with two members
circles.insert("alpha".to_string(), vec![
"04a1b2c3d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab".to_string(),
"04b2c3d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd".to_string(),
]);
// Circle "beta" with one member
circles.insert("beta".to_string(), vec![
"04c3d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(),
]);
// Circle "gamma" with three members
circles.insert("gamma".to_string(), vec![
"04d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01".to_string(),
"04e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123".to_string(),
"04f6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345".to_string(),
]);
// Build server with circle-based authentication
let server = ServerBuilder::new()
.host("127.0.0.1")
.port(8080)
.redis_url("redis://localhost:6379")
.with_auth()
.circles(circles)
.build()?;
println!("Starting WebSocket server with circle-based authentication...");
println!("Available circles:");
for (circle_id, members) in &server.circles {
println!(" Circle '{}' has {} members:", circle_id, members.len());
for (i, member) in members.iter().enumerate() {
println!(" Member {}: {}...{}", i + 1, &member[..10], &member[member.len()-10..]);
}
}
println!("\nTo connect to a specific circle, use URLs like:");
println!(" ws://127.0.0.1:8080/ws/alpha (for circle 'alpha')");
println!(" ws://127.0.0.1:8080/ws/beta (for circle 'beta')");
println!(" ws://127.0.0.1:8080/ws/gamma (for circle 'gamma')");
println!("\nAuthentication flow:");
println!("1. Connect to WebSocket URL for specific circle");
println!("2. Call 'fetch_nonce' method to get a nonce");
println!("3. Sign the nonce with your private key");
println!("4. Call 'authenticate' with your public key and signature");
println!("5. Server will verify signature AND check circle membership");
println!("6. Only members of the target circle will be authenticated");
// Start the server
let (task_handle, server_handle) = server.spawn_circle_server()?;
println!("\nServer started! Press Ctrl+C to stop.");
// Wait for the server to complete
match task_handle.await {
Ok(Ok(())) => println!("Server stopped successfully"),
Ok(Err(e)) => eprintln!("Server error: {}", e),
Err(e) => eprintln!("Task join error: {}", e),
}
Ok(())
}