aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 19:26:29 +0000
committertv <tv@krebsco.de>2026-11-08 20:27:20 +0100
commit83171090a0ff9cb9aeca3c1f91edff769076a5a7 (patch)
tree4a64910e841247649a516d7158acb7f87d65a251 /src/node.rs
parentc9c7807bf0f068474ce5c853244bcb392bdfcce3 (diff)
state: limit refused writes per user
A write every node would refuse is rolled back by forking the document at the heads before it, under the write lock, at a cost that grows with the document's history. A user could ask for such writes in a loop. Count each user's refused writes over the last minute. Past --refused-writes-per-minute (default 10), its writes are answered 429 without being tried, until the oldest refusal leaves the minute.
Diffstat (limited to 'src/node.rs')
-rw-r--r--src/node.rs4
1 files changed, 4 insertions, 0 deletions
diff --git a/src/node.rs b/src/node.rs
index 84a5c01..c74d7c0 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -78,6 +78,8 @@ pub(crate) struct NodeConfig {
/// `--challenge-lifetime`, `--key-logins-per-user`.
pub(crate) challenge_lifetime: Duration,
pub(crate) key_logins_per_user: usize,
+ /// `--refused-writes-per-minute`.
+ pub(crate) refused_writes_per_minute: usize,
/// `--genesis-root`.
pub(crate) genesis_root: Option<crate::document::ChangeHash>,
/// `--strict-keys`.
@@ -182,6 +184,8 @@ impl Node {
session_lifetime: config.session_lifetime,
challenge_lifetime: config.challenge_lifetime,
key_logins_per_user: config.key_logins_per_user,
+ refused_writes: Default::default(),
+ refused_writes_per_minute: config.refused_writes_per_minute,
strict_keys: Arc::new(config.strict_keys),
cors_origins: Arc::new(config.cors_origins),
state_file: config.state_file,