diff options
Diffstat (limited to 'src/access/envelope.rs')
| -rw-r--r-- | src/access/envelope.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/access/envelope.rs b/src/access/envelope.rs index 7cd0083..e99a06e 100644 --- a/src/access/envelope.rs +++ b/src/access/envelope.rs @@ -218,8 +218,8 @@ pub(crate) fn check( } /// Whether `payload`, signed by its user (`user`, enabled), is that user's own entry -/// with only its keys changed from the one at `path` in `doc`: a user manages its own -/// keys, whatever else it may do. +/// with only its keys changed from the one at `path` in `doc`, one left at least: a user +/// manages its own keys, whatever else it may do. fn own_keys_only( doc: &impl ReadDoc, payload: &Payload, @@ -232,6 +232,15 @@ fn own_keys_only( let Ok(Some(mut before)) = store::read_plain(doc, path) else { return false; }; + // One key left at least: a user can't sign, nor log in by key, without one. + if payload + .value + .get("keys") + .and_then(JsonValue::as_object) + .is_none_or(serde_json::Map::is_empty) + { + return false; + } let mut after = payload.value.clone(); for entry in [&mut before, &mut after] { match entry.as_object_mut() { @@ -355,6 +364,10 @@ mod tests { assert!(check(&doc, &signed_as("alice", more), &path(at), None).is_err()); // bob, holding the same key, for alice: not his entry. assert!(check(&doc, &signed_as("bob", rekeyed), &path(at), None).is_err()); + // Her keys all gone: no. + let mut keyless = entry.clone(); + keyless["keys"] = json!({}); + assert!(check(&doc, &signed_as("alice", keyless), &path(at), None).is_err()); } #[test] |
