diff --git a/warzone/Cargo.lock b/warzone/Cargo.lock index e89b1c2..46aa5da 100644 --- a/warzone/Cargo.lock +++ b/warzone/Cargo.lock @@ -2647,7 +2647,7 @@ dependencies = [ [[package]] name = "warzone-client" -version = "0.0.10" +version = "0.0.11" dependencies = [ "anyhow", "argon2", @@ -2680,7 +2680,7 @@ dependencies = [ [[package]] name = "warzone-mule" -version = "0.0.10" +version = "0.0.11" dependencies = [ "anyhow", "clap", @@ -2689,7 +2689,7 @@ dependencies = [ [[package]] name = "warzone-protocol" -version = "0.0.10" +version = "0.0.11" dependencies = [ "base64", "bincode", @@ -2712,7 +2712,7 @@ dependencies = [ [[package]] name = "warzone-server" -version = "0.0.10" +version = "0.0.11" dependencies = [ "anyhow", "axum", @@ -2739,7 +2739,7 @@ dependencies = [ [[package]] name = "warzone-wasm" -version = "0.0.10" +version = "0.0.11" dependencies = [ "base64", "bincode", diff --git a/warzone/Cargo.toml b/warzone/Cargo.toml index 95fb31d..d8de1a5 100644 --- a/warzone/Cargo.toml +++ b/warzone/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "0.0.10" +version = "0.0.11" edition = "2021" license = "MIT" rust-version = "1.75" diff --git a/warzone/crates/warzone-server/src/routes/keys.rs b/warzone/crates/warzone-server/src/routes/keys.rs index 4bbca98..87b5ebb 100644 --- a/warzone/crates/warzone-server/src/routes/keys.rs +++ b/warzone/crates/warzone-server/src/routes/keys.rs @@ -14,6 +14,7 @@ pub fn routes() -> Router { .route("/keys/list", get(list_keys)) .route("/keys/:fingerprint", get(get_bundle)) .route("/keys/:fingerprint/otpk-count", get(otpk_count)) + .route("/keys/:fingerprint/devices", get(list_devices)) } /// Debug endpoint: list all registered fingerprints. @@ -42,6 +43,8 @@ fn normalize_fp(fp: &str) -> String { #[derive(Deserialize)] struct RegisterRequest { fingerprint: String, + #[serde(default)] + device_id: Option, bundle: Vec, } @@ -54,9 +57,17 @@ async fn register_keys( State(state): State, Json(req): Json, ) -> Json { - let key = normalize_fp(&req.fingerprint); - tracing::info!("Registering bundle for {}", key); - let _ = state.db.keys.insert(key.as_bytes(), req.bundle); + let fp = normalize_fp(&req.fingerprint); + let device_id = req.device_id.unwrap_or_else(|| "default".to_string()); + + // Store bundle keyed by fingerprint (primary, used for lookup) + let _ = state.db.keys.insert(fp.as_bytes(), req.bundle.clone()); + + // Also store per-device: device:: → bundle + let device_key = format!("device:{}:{}", fp, device_id); + let _ = state.db.keys.insert(device_key.as_bytes(), req.bundle); + + tracing::info!("Registered bundle for {} (device: {})", fp, device_id); Json(RegisterResponse { ok: true }) } @@ -136,3 +147,22 @@ async fn replenish_otpks( tracing::info!("Replenished {} OTPKs for {} (total: {})", stored, fp, total); Json(serde_json::json!({ "ok": true, "stored": stored, "total": total })) } + +/// List all registered devices for a fingerprint. +async fn list_devices( + State(state): State, + Path(fingerprint): Path, +) -> Json { + let fp = normalize_fp(&fingerprint); + let prefix = format!("device:{}:", fp); + let devices: Vec = state.db.keys.scan_prefix(prefix.as_bytes()) + .filter_map(|item| { + item.ok().and_then(|(k, _)| { + let key_str = String::from_utf8_lossy(&k).to_string(); + // key format: device:: + key_str.rsplit(':').next().map(|s| s.to_string()) + }) + }) + .collect(); + Json(serde_json::json!({ "fingerprint": fp, "devices": devices, "count": devices.len() })) +}