diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c0079a83..6e3a6ecc 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -11,7 +11,6 @@ namespace CachetHQ\Cachet\Http; -use AltThree\Throttle\ThrottlingMiddleware; use Barryvdh\Cors\HandleCors; use CachetHQ\Cachet\Http\Middleware\Admin; use CachetHQ\Cachet\Http\Middleware\ApiAuthentication; @@ -21,6 +20,7 @@ use CachetHQ\Cachet\Http\Middleware\ReadyForUse; use CachetHQ\Cachet\Http\Middleware\RedirectIfAuthenticated; use CachetHQ\Cachet\Http\Middleware\SetupAlreadyCompleted; use CachetHQ\Cachet\Http\Middleware\SubscribersConfigured; +use CachetHQ\Cachet\Http\Middleware\Throttler; use CachetHQ\Cachet\Http\Middleware\TrustProxies; use Illuminate\Auth\Middleware\Authorize; use Illuminate\Foundation\Http\Kernel as HttpKernel; @@ -54,6 +54,6 @@ class Kernel extends HttpKernel 'ready' => ReadyForUse::class, 'setup' => SetupAlreadyCompleted::class, 'subscribers' => SubscribersConfigured::class, - 'throttle' => ThrottlingMiddleware::class, + 'throttle' => Throttler::class, ]; } diff --git a/app/Http/Middleware/Acceptable.php b/app/Http/Middleware/Acceptable.php index 7db13506..97974fa7 100644 --- a/app/Http/Middleware/Acceptable.php +++ b/app/Http/Middleware/Acceptable.php @@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; /** * This is the acceptable middleware class. * - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks */ class Acceptable diff --git a/app/Http/Middleware/Admin.php b/app/Http/Middleware/Admin.php index 5c83c821..4180c366 100644 --- a/app/Http/Middleware/Admin.php +++ b/app/Http/Middleware/Admin.php @@ -20,7 +20,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; * This is the admin middleware class. * * @author Joseph Cohen - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks */ class Admin diff --git a/app/Http/Middleware/ApiAuthentication.php b/app/Http/Middleware/ApiAuthentication.php index 0ae7a068..c02b6c08 100644 --- a/app/Http/Middleware/ApiAuthentication.php +++ b/app/Http/Middleware/ApiAuthentication.php @@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; * This is the api authentication middleware class. * * @author Joseph Cohen - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks */ class ApiAuthentication diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 6139df30..9b5562cb 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -20,7 +20,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; * This is the authenticate middleware class. * * @author Joseph Cohen - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks */ class Authenticate diff --git a/app/Http/Middleware/Localize.php b/app/Http/Middleware/Localize.php index 2c65f82b..52469c41 100644 --- a/app/Http/Middleware/Localize.php +++ b/app/Http/Middleware/Localize.php @@ -22,7 +22,7 @@ use Jenssegers\Date\Date; * * @author James Brooks * @author Joseph Cohen - * @author Graham Campbell + * @author Graham Campbell */ class Localize { diff --git a/app/Http/Middleware/ReadyForUse.php b/app/Http/Middleware/ReadyForUse.php index 1ae77e0c..11b1afbb 100644 --- a/app/Http/Middleware/ReadyForUse.php +++ b/app/Http/Middleware/ReadyForUse.php @@ -18,7 +18,7 @@ use Illuminate\Http\Request; /** * This is the ready for use middleware class. * - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks * @author Joseph Cohen */ diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 7c85f668..b8c95648 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -18,7 +18,7 @@ use Illuminate\Http\Request; /** * This is the redirect if authenticated middleware class. * - * @author Graham Campbell + * @author Graham Campbell * @author Joseph Cohen * @author James Brooks */ diff --git a/app/Http/Middleware/SetupAlreadyCompleted.php b/app/Http/Middleware/SetupAlreadyCompleted.php index 0a7be715..e0df0c8f 100644 --- a/app/Http/Middleware/SetupAlreadyCompleted.php +++ b/app/Http/Middleware/SetupAlreadyCompleted.php @@ -19,7 +19,7 @@ use Illuminate\Http\Request; /** * This is the setup already completed middelware class. * - * @author Graham Campbell + * @author Graham Campbell * @author James Brooks * @author Joseph Cohen */ diff --git a/app/Http/Middleware/SubscribersConfigured.php b/app/Http/Middleware/SubscribersConfigured.php index a8bc4056..b154b435 100644 --- a/app/Http/Middleware/SubscribersConfigured.php +++ b/app/Http/Middleware/SubscribersConfigured.php @@ -19,7 +19,7 @@ use Illuminate\Http\Request; * This is the subscribers configured middleware class. * * @author James Brooks - * @author Graham Campbell + * @author Graham Campbell */ class SubscribersConfigured { diff --git a/app/Http/Middleware/Throttler.php b/app/Http/Middleware/Throttler.php new file mode 100644 index 00000000..c8314963 --- /dev/null +++ b/app/Http/Middleware/Throttler.php @@ -0,0 +1,125 @@ + + */ +class Throttler +{ + /** + * The rate limiter instance. + * + * @var \Illuminate\Cache\RateLimiter + */ + protected $limiter; + + /** + * Create a new throttler middleware instance. + * + * @param \Illuminate\Cache\RateLimiter $limiter + * + * @return void + */ + public function __construct(RateLimiter $limiter) + { + $this->limiter = $limiter; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param int|string $limit + * @param int|string $decay + * + * @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException + * + * @return mixed + */ + public function handle(Request $request, Closure $next, $limit = 60, $decay = 1) + { + return $this->safeHandle($request, $next, (int) $limit, (int) $decay); + } + + /** + * Handle an incoming request, with correct types. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param int $limit + * @param int $decay + * + * @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException + * + * @return mixed + */ + protected function safeHandle(Request $request, Closure $next, int $limit, int $decay) + { + $key = $request->fingerprint(); + + if ($this->limiter->tooManyAttempts($key, $limit, $decay)) { + throw $this->buildException($key, $limit); + } + + $this->limiter->hit($key, $decay); + + $response = $next($request); + + $response->headers->add($this->getHeaders($key, $limit)); + + return $response; + } + + /** + * Create a too many requests http exception. + * + * @param string $key + * @param int $limit + * + * @return \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException + */ + protected function buildException(string $key, int $limit) + { + $after = $this->limiter->availableIn($key); + $exception = new TooManyRequestsHttpException($after, 'Rate limit exceeded.'); + $exception->setHeaders($this->getHeaders($key, $limit, $after, $exception->getHeaders())); + + return $exception; + } + + /** + * Get the limit header information. + * + * @param string $key + * @param int $limit + * @param int|null $after + * @param array $merge + * + * @return array + */ + protected function getHeaders(string $key, int $limit, int $after = null, array $merge = []) + { + $remaining = $after === null ? $this->limiter->retriesLeft($key, $limit) : 0; + $headers = ['X-RateLimit-Limit' => $limit, 'X-RateLimit-Remaining' => $remaining]; + + return array_merge($headers, $merge); + } +} diff --git a/app/Http/Middleware/Timezone.php b/app/Http/Middleware/Timezone.php index 40afe9e0..e0700714 100644 --- a/app/Http/Middleware/Timezone.php +++ b/app/Http/Middleware/Timezone.php @@ -19,7 +19,7 @@ use Illuminate\Http\Request; * This is the timezone middleware class. * * @author James Brooks - * @author Graham Campbell + * @author Graham Campbell */ class Timezone { diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 03736d46..cfd2fc05 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -13,6 +13,11 @@ namespace CachetHQ\Cachet\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; +/** + * This is the verify csrf token middleware class. + * + * @author James Brooks + */ class VerifyCsrfToken extends Middleware { /** diff --git a/composer.json b/composer.json index c10abe3c..31e914b0 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,6 @@ "alt-three/badger": "^5.1", "alt-three/bus": "^4.1", "alt-three/emoji": "^7.0", - "alt-three/throttle": "^3.1", "alt-three/twitter": "^3.1", "alt-three/validator": "^4.1", "aws/aws-sdk-php": "^3.7", diff --git a/composer.lock b/composer.lock index 1cff9d81..33e75bb2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3af019a3c33715f7f196fd405978e49d", + "content-hash": "0aaa508129681e69c71b9c7f7380cf81", "packages": [ { "name": "alt-three/badger", @@ -187,61 +187,6 @@ ], "time": "2018-12-28T16:34:12+00:00" }, - { - "name": "alt-three/throttle", - "version": "v3.1.0", - "source": { - "type": "git", - "url": "https://github.com/AltThree/Throttle.git", - "reference": "6f85d5dac57ad1092983b64bb59650e9096c9385" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/AltThree/Throttle/zipball/6f85d5dac57ad1092983b64bb59650e9096c9385", - "reference": "6f85d5dac57ad1092983b64bb59650e9096c9385", - "shasum": "" - }, - "require": { - "illuminate/cache": "5.5.*|5.6.*|5.7.*", - "illuminate/http": "5.5.*|5.6.*|5.7.*", - "php": "^7.1.3" - }, - "require-dev": { - "graham-campbell/analyzer": "^2.1", - "graham-campbell/testbench": "^5.1", - "phpunit/phpunit": "^6.5|^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "AltThree\\Throttle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alt Three", - "email": "support@alt-three.com" - } - ], - "description": "A request rate limiter for Laravel 5.2+", - "keywords": [ - "Alt Three", - "http", - "rate limit", - "rate limiter", - "throttle" - ], - "time": "2018-09-29T10:43:47+00:00" - }, { "name": "alt-three/twitter", "version": "v3.1.0", @@ -410,16 +355,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.87.5", + "version": "3.87.8", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "77bbcf213972b7e9ddf4fd101ef5f521adac9f7f" + "reference": "28f117c221ee53dc2486ffcbf7288a9af6d21612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/77bbcf213972b7e9ddf4fd101ef5f521adac9f7f", - "reference": "77bbcf213972b7e9ddf4fd101ef5f521adac9f7f", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/28f117c221ee53dc2486ffcbf7288a9af6d21612", + "reference": "28f117c221ee53dc2486ffcbf7288a9af6d21612", "shasum": "" }, "require": { @@ -488,7 +433,7 @@ "s3", "sdk" ], - "time": "2019-02-06T23:17:08+00:00" + "time": "2019-02-11T23:07:51+00:00" }, { "name": "bacon/bacon-qr-code", @@ -5520,16 +5465,16 @@ }, { "name": "mockery/mockery", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "100633629bf76d57430b86b7098cd6beb996a35a" + "reference": "dc4f10b6b1148744facb784015e4b339d7feec23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/100633629bf76d57430b86b7098cd6beb996a35a", - "reference": "100633629bf76d57430b86b7098cd6beb996a35a", + "url": "https://api.github.com/repos/mockery/mockery/zipball/dc4f10b6b1148744facb784015e4b339d7feec23", + "reference": "dc4f10b6b1148744facb784015e4b339d7feec23", "shasum": "" }, "require": { @@ -5538,7 +5483,7 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "~5.7.10|~6.5|~7.0" + "phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0" }, "type": "library", "extra": { @@ -5581,7 +5526,7 @@ "test double", "testing" ], - "time": "2018-10-02T21:52:37+00:00" + "time": "2019-02-08T14:43:54+00:00" }, { "name": "myclabs/deep-copy",