use chrono::Duration;
use tiny_counter::{EventId, EventStore, TimeUnit};
#[derive(Debug, Clone, Copy)]
enum SecurityEvent {
LoginAttempt,
LoginSuccess,
LoginFailed,
ApiCall,
}
impl AsRef<str> for SecurityEvent {
fn as_ref(&self) -> &str {
match self {
SecurityEvent::LoginAttempt => "security:login:attempt",
SecurityEvent::LoginSuccess => "security:login:success",
SecurityEvent::LoginFailed => "security:login:failed",
SecurityEvent::ApiCall => "security:api:call",
}
}
}
impl EventId for SecurityEvent {}
fn main() {
println!("=== Security Patterns Examples ===\n");
println!("1. Brute force protection:");
let store = EventStore::new();
for i in 1..=8 {
let result = store
.limit()
.at_most(SecurityEvent::LoginAttempt, 5, TimeUnit::Minutes)
.at_most(SecurityEvent::LoginAttempt, 20, TimeUnit::Hours)
.check_and_record(SecurityEvent::LoginAttempt);
match result {
Ok(()) => println!(" Login attempt {}: ✓ Allowed", i),
Err(e) => println!(" Login attempt {}: ✗ Rate limited - {}", i, e),
}
}
println!("\n2. Progressive backoff after failures:");
let store = EventStore::new();
for _ in 0..4 {
store.record(SecurityEvent::LoginFailed);
}
let failed_attempts = store
.query(SecurityEvent::LoginFailed)
.last_minutes(15)
.sum()
.unwrap_or(0);
println!(" Failed attempts in last 15 minutes: {}", failed_attempts);
let cooldown_seconds = match failed_attempts {
0..=2 => 0,
3..=5 => 30,
6..=10 => 300, _ => 1800, };
println!(" Required cooldown: {} seconds", cooldown_seconds);
if cooldown_seconds > 0 {
let result = store
.limit()
.cooldown(
SecurityEvent::LoginAttempt,
Duration::seconds(cooldown_seconds),
)
.check_and_record(SecurityEvent::LoginAttempt);
match result {
Ok(()) => println!(" Next login attempt: ✓ Allowed (cooldown expired)"),
Err(_) => println!(" Next login attempt: ✗ Cooldown active"),
}
}
println!("\n3. Anomaly detection:");
let store = EventStore::new();
store.record_count(SecurityEvent::ApiCall, 300);
let baseline = store
.query(SecurityEvent::ApiCall)
.last_days(30)
.average()
.unwrap_or(10.0);
println!(" Baseline: {:.1} calls/day", baseline);
store.record_count(SecurityEvent::ApiCall, 100);
let current = store
.query(SecurityEvent::ApiCall)
.last_hours(1)
.sum()
.unwrap_or(0) as f64;
println!(" Current hour: {} calls", current);
let threshold = baseline * 5.0;
if current > threshold {
println!(
" ⚠️ ALERT: Activity {} exceeds threshold {:.1}",
current, threshold
);
println!(" ({}x normal rate)", current / baseline);
} else {
println!(" Activity within normal range");
}
println!("\n4. Multi-layer security:");
let store = EventStore::new();
let result = store
.limit()
.at_most(SecurityEvent::LoginAttempt, 3, TimeUnit::Minutes)
.at_most(SecurityEvent::LoginAttempt, 10, TimeUnit::Hours)
.cooldown(SecurityEvent::LoginFailed, Duration::seconds(60))
.check_and_record(SecurityEvent::LoginAttempt);
println!(" Checking multiple security constraints:");
println!(" - Max 3 attempts per minute");
println!(" - Max 10 attempts per hour");
println!(" - 60-second cooldown after failures");
match result {
Ok(()) => println!(" Result: ✓ All constraints passed"),
Err(e) => println!(" Result: ✗ Constraint violated - {}", e),
}
println!("\n5. Complete authentication workflow:");
let store = EventStore::new();
fn attempt_login(store: &EventStore, password_correct: bool) -> bool {
let can_attempt = store
.limit()
.at_most(SecurityEvent::LoginAttempt, 5, TimeUnit::Minutes)
.at_most(SecurityEvent::LoginAttempt, 20, TimeUnit::Hours)
.check_and_record(SecurityEvent::LoginAttempt);
if can_attempt.is_err() {
println!(" Rate limited");
return false;
}
if password_correct {
store.record(SecurityEvent::LoginSuccess);
println!(" ✓ Login successful");
true
} else {
store.record(SecurityEvent::LoginFailed);
println!(" ✗ Login failed");
false
}
}
println!(" Attempting logins:");
println!(" Attempt 1 (wrong password):");
attempt_login(&store, false);
println!(" Attempt 2 (wrong password):");
attempt_login(&store, false);
println!(" Attempt 3 (correct password):");
attempt_login(&store, true);
let success_rate = store
.query_ratio(SecurityEvent::LoginSuccess, SecurityEvent::LoginAttempt)
.last_hours(1);
if let Some(rate) = success_rate {
println!(" Success rate: {:.1}%", rate * 100.0);
}
println!("\n6. Account lockout after repeated failures:");
let store = EventStore::new();
for _ in 0..6 {
store.record(SecurityEvent::LoginFailed);
}
let failures = store
.query(SecurityEvent::LoginFailed)
.last_hours(1)
.sum()
.unwrap_or(0);
println!(" Failed attempts in last hour: {}", failures);
if failures >= 5 {
println!(" ⚠️ Account locked");
println!(" Action required: Admin review or wait 1 hour");
let result = store
.limit()
.at_most(SecurityEvent::LoginAttempt, 0, TimeUnit::Hours) .check_and_record(SecurityEvent::LoginAttempt);
match result {
Ok(()) => println!(" Login: ✓ Allowed"),
Err(_) => println!(" Login: ✗ Blocked (account locked)"),
}
} else {
println!(" Account status: Active");
}
println!("\n✓ Security patterns complete!");
}