Skip to content
This repository has been archived by the owner on Sep 10, 2024. It is now read-only.

Commit

Permalink
fixup! Add configuration for rate-limiting of logins, replacing hardc…
Browse files Browse the repository at this point in the history
…oded limits
  • Loading branch information
reivilibre committed Aug 7, 2024
1 parent 11abd7a commit 8df3ec4
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 12 deletions.
16 changes: 5 additions & 11 deletions crates/config/src/sections/rate_limiting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{num::NonZero, time::Duration};
use std::{num::NonZeroU32, time::Duration};

use governor::Quota;
use schemars::JsonSchema;
Expand Down Expand Up @@ -54,8 +54,7 @@ pub struct LoginRateLimitingConfig {
pub struct RateLimiterConfiguration {
/// A one-off burst of actions that the user can perform
/// in one go without waiting.
/// Replenishes at the rate.
pub burst: u32,
pub burst: NonZeroU32,
/// How quickly the allowance replenishes, in number of actions per second.
/// Can be fractional to replenish slower.
pub per_second: f64,
Expand All @@ -82,10 +81,6 @@ impl ConfigurationSection for RateLimitingConfig {
// Check one limiter's configuration for errors
let error_on_limiter =
|limiter: &RateLimiterConfiguration| -> Option<figment::error::Error> {
if limiter.burst == 0 {
return Some(figment::error::Error::custom("`burst` must not be zero, as this would mean the action could never be performed"));
}

let recip = limiter.per_second.recip();
// period must be at least 1 nanosecond according to the governor library
if recip < 1.0e-9 || !recip.is_finite() {
Expand Down Expand Up @@ -120,21 +115,20 @@ impl RateLimiterConfiguration {
if !reciprocal.is_finite() {
return None;
}
let burst = NonZero::new(self.burst)?;
Some(Quota::with_period(Duration::from_secs_f64(reciprocal))?.allow_burst(burst))
Some(Quota::with_period(Duration::from_secs_f64(reciprocal))?.allow_burst(self.burst))
}
}

fn default_login_per_address() -> RateLimiterConfiguration {
RateLimiterConfiguration {
burst: 3,
burst: NonZeroU32::new(3).unwrap(),
per_second: 3.0 / 60.0,
}
}

fn default_login_per_account() -> RateLimiterConfiguration {
RateLimiterConfiguration {
burst: 1800,
burst: NonZeroU32::new(1800).unwrap(),
per_second: 1800.0 / 3600.0,
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1726,7 +1726,7 @@
"description": "A one-off burst of actions that the user can perform in one go without waiting. Replenishes at the rate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
"minimum": 1.0
},
"per_second": {
"description": "How quickly the allowance replenishes, in number of actions per second. Can be fractional to replenish slower.",
Expand Down

0 comments on commit 8df3ec4

Please sign in to comment.