aboutsummaryrefslogtreecommitdiffhomepage
path: root/main/app/sprinkles/core/src/Throttle
diff options
context:
space:
mode:
authorMarvin Borner2018-06-08 20:03:25 +0200
committerMarvin Borner2018-06-08 20:03:25 +0200
commit92b7dd3335a6572debeacfb5faa82c63a5e67888 (patch)
tree7ebbca22595d542ec5e2912a24a0400ac8f6b113 /main/app/sprinkles/core/src/Throttle
parent22a1bb27f94ea33042b0bdd35bef1a5cfa96cc0d (diff)
Some minor fixes
Diffstat (limited to 'main/app/sprinkles/core/src/Throttle')
-rw-r--r--main/app/sprinkles/core/src/Throttle/ThrottleRule.php266
-rw-r--r--main/app/sprinkles/core/src/Throttle/Throttler.php344
-rw-r--r--main/app/sprinkles/core/src/Throttle/ThrottlerException.php38
3 files changed, 324 insertions, 324 deletions
diff --git a/main/app/sprinkles/core/src/Throttle/ThrottleRule.php b/main/app/sprinkles/core/src/Throttle/ThrottleRule.php
index c5e0c82..5840027 100644
--- a/main/app/sprinkles/core/src/Throttle/ThrottleRule.php
+++ b/main/app/sprinkles/core/src/Throttle/ThrottleRule.php
@@ -1,133 +1,133 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Throttle;
-
-/**
- * ThrottleRule Class
- *
- * Represents a request throttling rule.
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ThrottleRule
-{
- /** @var string Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. */
- protected $method;
-
- /** @var int The amount of time, in seconds, to look back in determining attempts to consider. */
- protected $interval;
-
- /**
- * @var int[] A mapping of minimum observation counts (x) to delays (y), in seconds.
- * Any throttleable event that has occurred more than x times in this rule's interval,
- * must wait y seconds after the last occurrence before another attempt is permitted.
- */
- protected $delays;
-
- /**
- * Create a new ThrottleRule object.
- *
- * @param string $method Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling.
- * @param int $interval The amount of time, in seconds, to look back in determining attempts to consider.
- * @param int[] $delays A mapping of minimum observation counts (x) to delays (y), in seconds.
- */
- public function __construct($method, $interval, $delays) {
- $this->setMethod($method);
- $this->setInterval($interval);
- $this->setDelays($delays);
- }
-
- /**
- * Get the current delay on this rule for a particular number of event counts.
- *
- * @param Carbon\Carbon $lastEventTime The timestamp for the last countable event.
- * @param int $count The total number of events which have occurred in an interval.
- */
- public function getDelay($lastEventTime, $count) {
- // Zero occurrences always maps to a delay of 0 seconds.
- if ($count == 0) {
- return 0;
- }
-
- foreach ($this->delays as $observations => $delay) {
- // Skip any delay rules for which we haven't met the requisite number of observations
- if ($count < $observations) {
- continue;
- }
-
- // If this rule meets the observed number of events, and violates the required delay, then return the remaining time left
- if ($lastEventTime->diffInSeconds() < $delay) {
- return $lastEventTime->addSeconds($delay)->diffInSeconds();
- }
- }
-
- return 0;
- }
-
- /**
- * Gets the current mapping of attempts (int) to delays (seconds).
- *
- * @return int[]
- */
- public function getDelays() {
- return $this->delays;
- }
-
- /**
- * Gets the current throttling interval (seconds).
- *
- * @return int
- */
- public function getInterval() {
- return $this->interval;
- }
-
- /**
- * Gets the current throttling method ('ip' or 'data').
- *
- * @return string
- */
- public function getMethod() {
- return $this->method;
- }
-
- /**
- * Sets the current mapping of attempts (int) to delays (seconds).
- *
- * @param int[] A mapping of minimum observation counts (x) to delays (y), in seconds.
- */
- public function setDelays($delays) {
- // Sort the array by key, from highest to lowest value
- $this->delays = $delays;
- krsort($this->delays);
-
- return $this;
- }
-
- /**
- * Sets the current throttling interval (seconds).
- *
- * @param int The amount of time, in seconds, to look back in determining attempts to consider.
- */
- public function setInterval($interval) {
- $this->interval = $interval;
-
- return $this;
- }
-
- /**
- * Sets the current throttling method ('ip' or 'data').
- *
- * @param string Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling.
- */
- public function setMethod($method) {
- $this->method = $method;
-
- return $this;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Throttle;
+
+/**
+ * ThrottleRule Class
+ *
+ * Represents a request throttling rule.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ThrottleRule
+{
+ /** @var string Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. */
+ protected $method;
+
+ /** @var int The amount of time, in seconds, to look back in determining attempts to consider. */
+ protected $interval;
+
+ /**
+ * @var int[] A mapping of minimum observation counts (x) to delays (y), in seconds.
+ * Any throttleable event that has occurred more than x times in this rule's interval,
+ * must wait y seconds after the last occurrence before another attempt is permitted.
+ */
+ protected $delays;
+
+ /**
+ * Create a new ThrottleRule object.
+ *
+ * @param string $method Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling.
+ * @param int $interval The amount of time, in seconds, to look back in determining attempts to consider.
+ * @param int[] $delays A mapping of minimum observation counts (x) to delays (y), in seconds.
+ */
+ public function __construct($method, $interval, $delays) {
+ $this->setMethod($method);
+ $this->setInterval($interval);
+ $this->setDelays($delays);
+ }
+
+ /**
+ * Get the current delay on this rule for a particular number of event counts.
+ *
+ * @param Carbon\Carbon $lastEventTime The timestamp for the last countable event.
+ * @param int $count The total number of events which have occurred in an interval.
+ */
+ public function getDelay($lastEventTime, $count) {
+ // Zero occurrences always maps to a delay of 0 seconds.
+ if ($count == 0) {
+ return 0;
+ }
+
+ foreach ($this->delays as $observations => $delay) {
+ // Skip any delay rules for which we haven't met the requisite number of observations
+ if ($count < $observations) {
+ continue;
+ }
+
+ // If this rule meets the observed number of events, and violates the required delay, then return the remaining time left
+ if ($lastEventTime->diffInSeconds() < $delay) {
+ return $lastEventTime->addSeconds($delay)->diffInSeconds();
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Gets the current mapping of attempts (int) to delays (seconds).
+ *
+ * @return int[]
+ */
+ public function getDelays() {
+ return $this->delays;
+ }
+
+ /**
+ * Gets the current throttling interval (seconds).
+ *
+ * @return int
+ */
+ public function getInterval() {
+ return $this->interval;
+ }
+
+ /**
+ * Gets the current throttling method ('ip' or 'data').
+ *
+ * @return string
+ */
+ public function getMethod() {
+ return $this->method;
+ }
+
+ /**
+ * Sets the current mapping of attempts (int) to delays (seconds).
+ *
+ * @param int[] A mapping of minimum observation counts (x) to delays (y), in seconds.
+ */
+ public function setDelays($delays) {
+ // Sort the array by key, from highest to lowest value
+ $this->delays = $delays;
+ krsort($this->delays);
+
+ return $this;
+ }
+
+ /**
+ * Sets the current throttling interval (seconds).
+ *
+ * @param int The amount of time, in seconds, to look back in determining attempts to consider.
+ */
+ public function setInterval($interval) {
+ $this->interval = $interval;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current throttling method ('ip' or 'data').
+ *
+ * @param string Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling.
+ */
+ public function setMethod($method) {
+ $this->method = $method;
+
+ return $this;
+ }
+}
diff --git a/main/app/sprinkles/core/src/Throttle/Throttler.php b/main/app/sprinkles/core/src/Throttle/Throttler.php
index 4ab9dd6..f7d1cc7 100644
--- a/main/app/sprinkles/core/src/Throttle/Throttler.php
+++ b/main/app/sprinkles/core/src/Throttle/Throttler.php
@@ -1,172 +1,172 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Throttle;
-
-use Carbon\Carbon;
-use UserFrosting\Sprinkle\Core\Util\ClassMapper;
-
-/**
- * Handles throttling (rate limiting) of specific types of requests.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Throttler
-{
- /**
- * @var UserFrosting\Sprinkle\Core\Util\ClassMapper
- */
- protected $classMapper;
-
- /**
- * @var ThrottleRule[] An array mapping throttle names to throttle rules.
- */
- protected $throttleRules;
-
- /**
- * Create a new Throttler object.
- *
- * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
- */
- public function __construct(ClassMapper $classMapper) {
- $this->classMapper = $classMapper;
- $this->throttleRules = [];
- }
-
- /**
- * Add a throttling rule for a particular throttle event type.
- *
- * @param string $type The type of throttle event to check against.
- * @param ThrottleRule $rule The rule to use when throttling this type of event.
- */
- public function addThrottleRule($type, $rule) {
- if (!($rule instanceof ThrottleRule || ($rule === NULL))) {
- throw new ThrottlerException('$rule must be of type ThrottleRule (or null).');
- }
-
- $this->throttleRules[$type] = $rule;
-
- return $this;
- }
-
- /**
- * Check the current request against a specified throttle rule.
- *
- * @param string $type The type of throttle event to check against.
- * @param mixed[] $requestData Any additional request parameters to use in checking the throttle.
- * @return bool
- */
- public function getDelay($type, $requestData = []) {
- $throttleRule = $this->getRule($type);
-
- if (is_null($throttleRule)) {
- return 0;
- }
-
- // Get earliest time to start looking for throttleable events
- $startTime = Carbon::now()
- ->subSeconds($throttleRule->getInterval());
-
- // Fetch all throttle events of the specified type, that match the specified rule
- if ($throttleRule->getMethod() == 'ip') {
- $events = $this->classMapper->staticMethod('throttle', 'where', 'type', $type)
- ->where('created_at', '>', $startTime)
- ->where('ip', $_SERVER['REMOTE_ADDR'])
- ->get();
- } else {
- $events = $this->classMapper->staticMethod('throttle', 'where', 'type', $type)
- ->where('created_at', '>', $startTime)
- ->get();
-
- // Filter out only events that match the required JSON data
- $events = $events->filter(function ($item, $key) use ($requestData) {
- $data = json_decode($item->request_data);
-
- // If a field is not specified in the logged data, or it doesn't match the value we're searching for,
- // then filter out this event from the collection.
- foreach ($requestData as $name => $value) {
- if (!isset($data->$name) || ($data->$name != $value)) {
- return FALSE;
- }
- }
-
- return TRUE;
- });
- }
-
- // Check the collection of events against the specified throttle rule.
- return $this->computeDelay($events, $throttleRule);
- }
-
- /**
- * Get a registered rule of a particular type.
- *
- * @param string $type
- * @throws ThrottlerException
- * @return ThrottleRule[]
- */
- public function getRule($type) {
- if (!array_key_exists($type, $this->throttleRules)) {
- throw new ThrottlerException("The throttling rule for '$type' could not be found.");
- }
-
- return $this->throttleRules[$type];
- }
-
- /**
- * Get the current throttling rules.
- *
- * @return ThrottleRule[]
- */
- public function getThrottleRules() {
- return $this->throttleRules;
- }
-
- /**
- * Log a throttleable event to the database.
- *
- * @param string $type the type of event
- * @param string[] $requestData an array of field names => values that are relevant to throttling for this event (e.g. username, email, etc).
- */
- public function logEvent($type, $requestData = []) {
- // Just a check to make sure the rule exists
- $throttleRule = $this->getRule($type);
-
- if (is_null($throttleRule)) {
- return $this;
- }
-
- $event = $this->classMapper->createInstance('throttle', [
- 'type' => $type,
- 'ip' => $_SERVER['REMOTE_ADDR'],
- 'request_data' => json_encode($requestData)
- ]);
-
- $event->save();
-
- return $this;
- }
-
- /**
- * Returns the current delay for a specified throttle rule.
- *
- * @param Throttle[] $events a Collection of throttle events.
- * @param ThrottleRule $throttleRule a rule representing the strategy to use for throttling a particular type of event.
- * @return int seconds remaining until a particular event is permitted to be attempted again.
- */
- protected function computeDelay($events, $throttleRule) {
- // If no matching events found, then there is no delay
- if (!$events->count()) {
- return 0;
- }
-
- // Great, now we compare our delay against the most recent attempt
- $lastEvent = $events->last();
- return $throttleRule->getDelay($lastEvent->created_at, $events->count());
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Throttle;
+
+use Carbon\Carbon;
+use UserFrosting\Sprinkle\Core\Util\ClassMapper;
+
+/**
+ * Handles throttling (rate limiting) of specific types of requests.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Throttler
+{
+ /**
+ * @var UserFrosting\Sprinkle\Core\Util\ClassMapper
+ */
+ protected $classMapper;
+
+ /**
+ * @var ThrottleRule[] An array mapping throttle names to throttle rules.
+ */
+ protected $throttleRules;
+
+ /**
+ * Create a new Throttler object.
+ *
+ * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
+ */
+ public function __construct(ClassMapper $classMapper) {
+ $this->classMapper = $classMapper;
+ $this->throttleRules = [];
+ }
+
+ /**
+ * Add a throttling rule for a particular throttle event type.
+ *
+ * @param string $type The type of throttle event to check against.
+ * @param ThrottleRule $rule The rule to use when throttling this type of event.
+ */
+ public function addThrottleRule($type, $rule) {
+ if (!($rule instanceof ThrottleRule || ($rule === NULL))) {
+ throw new ThrottlerException('$rule must be of type ThrottleRule (or null).');
+ }
+
+ $this->throttleRules[$type] = $rule;
+
+ return $this;
+ }
+
+ /**
+ * Check the current request against a specified throttle rule.
+ *
+ * @param string $type The type of throttle event to check against.
+ * @param mixed[] $requestData Any additional request parameters to use in checking the throttle.
+ * @return bool
+ */
+ public function getDelay($type, $requestData = []) {
+ $throttleRule = $this->getRule($type);
+
+ if (is_null($throttleRule)) {
+ return 0;
+ }
+
+ // Get earliest time to start looking for throttleable events
+ $startTime = Carbon::now()
+ ->subSeconds($throttleRule->getInterval());
+
+ // Fetch all throttle events of the specified type, that match the specified rule
+ if ($throttleRule->getMethod() == 'ip') {
+ $events = $this->classMapper->staticMethod('throttle', 'where', 'type', $type)
+ ->where('created_at', '>', $startTime)
+ ->where('ip', $_SERVER['REMOTE_ADDR'])
+ ->get();
+ } else {
+ $events = $this->classMapper->staticMethod('throttle', 'where', 'type', $type)
+ ->where('created_at', '>', $startTime)
+ ->get();
+
+ // Filter out only events that match the required JSON data
+ $events = $events->filter(function ($item, $key) use ($requestData) {
+ $data = json_decode($item->request_data);
+
+ // If a field is not specified in the logged data, or it doesn't match the value we're searching for,
+ // then filter out this event from the collection.
+ foreach ($requestData as $name => $value) {
+ if (!isset($data->$name) || ($data->$name != $value)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ });
+ }
+
+ // Check the collection of events against the specified throttle rule.
+ return $this->computeDelay($events, $throttleRule);
+ }
+
+ /**
+ * Get a registered rule of a particular type.
+ *
+ * @param string $type
+ * @throws ThrottlerException
+ * @return ThrottleRule[]
+ */
+ public function getRule($type) {
+ if (!array_key_exists($type, $this->throttleRules)) {
+ throw new ThrottlerException("The throttling rule for '$type' could not be found.");
+ }
+
+ return $this->throttleRules[$type];
+ }
+
+ /**
+ * Get the current throttling rules.
+ *
+ * @return ThrottleRule[]
+ */
+ public function getThrottleRules() {
+ return $this->throttleRules;
+ }
+
+ /**
+ * Log a throttleable event to the database.
+ *
+ * @param string $type the type of event
+ * @param string[] $requestData an array of field names => values that are relevant to throttling for this event (e.g. username, email, etc).
+ */
+ public function logEvent($type, $requestData = []) {
+ // Just a check to make sure the rule exists
+ $throttleRule = $this->getRule($type);
+
+ if (is_null($throttleRule)) {
+ return $this;
+ }
+
+ $event = $this->classMapper->createInstance('throttle', [
+ 'type' => $type,
+ 'ip' => $_SERVER['REMOTE_ADDR'],
+ 'request_data' => json_encode($requestData)
+ ]);
+
+ $event->save();
+
+ return $this;
+ }
+
+ /**
+ * Returns the current delay for a specified throttle rule.
+ *
+ * @param Throttle[] $events a Collection of throttle events.
+ * @param ThrottleRule $throttleRule a rule representing the strategy to use for throttling a particular type of event.
+ * @return int seconds remaining until a particular event is permitted to be attempted again.
+ */
+ protected function computeDelay($events, $throttleRule) {
+ // If no matching events found, then there is no delay
+ if (!$events->count()) {
+ return 0;
+ }
+
+ // Great, now we compare our delay against the most recent attempt
+ $lastEvent = $events->last();
+ return $throttleRule->getDelay($lastEvent->created_at, $events->count());
+ }
+}
diff --git a/main/app/sprinkles/core/src/Throttle/ThrottlerException.php b/main/app/sprinkles/core/src/Throttle/ThrottlerException.php
index 08f2919..af29bc8 100644
--- a/main/app/sprinkles/core/src/Throttle/ThrottlerException.php
+++ b/main/app/sprinkles/core/src/Throttle/ThrottlerException.php
@@ -1,19 +1,19 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Throttle;
-
-/**
- * Throttler exception. Used when there is a problem with the request throttler.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ThrottlerException extends \RuntimeException
-{
-
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Throttle;
+
+/**
+ * Throttler exception. Used when there is a problem with the request throttler.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ThrottlerException extends \RuntimeException
+{
+
+}