store = $store; $this->hasher = $hasher; } /** * Get check name. */ public function get_name(): string { return 'rate_limit'; } /** * Whether the check is enabled. * * @param SettingsSnapshot $settings Immutable settings snapshot. */ public function is_enabled( SettingsSnapshot $settings ): bool { return $settings->is_check_enabled( 'rate_limit_check_enabled' ); } /** * Evaluate rate limit. * * @param SubmissionContext $context Normalized submission context. * @param SettingsSnapshot $settings Immutable settings snapshot. */ public function evaluate( SubmissionContext $context, SettingsSnapshot $settings ): CheckResult { $identifier = $context->get_rate_limit_identifier(); if ( '' === $identifier ) { return CheckResult::pass(); } $key = $this->hasher->hash_identifier( 'rate_limit', $identifier ); $count = $this->store->increment( $key, $settings->get_rate_limit_window_seconds(), $context->get_timestamp() ); if ( $count > $settings->get_rate_limit_threshold() ) { return CheckResult::block( ReasonCodeRegistry::RATE_LIMIT_EXCEEDED ); } return CheckResult::pass(); } }