From 49379bd1154827a73d7eeaf8f141ff20f42788a0 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 19 Nov 2017 14:34:55 -0600 Subject: [PATCH] Pop some tests for new middleware in there. --- app/Http/Middleware/API/AuthenticateKey.php | 14 +-- .../API/AuthenticateIPAccessTest.php | 82 +++++++++++++++++ .../Middleware/API/AuthenticateKeyTest.php | 90 +++++++++++++++++++ .../Middleware/API/SetSessionDriverTest.php | 69 ++++++++++++++ 4 files changed, 245 insertions(+), 10 deletions(-) create mode 100644 tests/Unit/Http/Middleware/API/AuthenticateIPAccessTest.php create mode 100644 tests/Unit/Http/Middleware/API/AuthenticateKeyTest.php create mode 100644 tests/Unit/Http/Middleware/API/SetSessionDriverTest.php diff --git a/app/Http/Middleware/API/AuthenticateKey.php b/app/Http/Middleware/API/AuthenticateKey.php index 0bad6dcb2..eb82682cc 100644 --- a/app/Http/Middleware/API/AuthenticateKey.php +++ b/app/Http/Middleware/API/AuthenticateKey.php @@ -7,7 +7,6 @@ use Illuminate\Http\Request; use Illuminate\Auth\AuthManager; use Symfony\Component\HttpKernel\Exception\HttpException; use Pterodactyl\Exceptions\Repository\RecordNotFoundException; -use Illuminate\Contracts\Config\Repository as ConfigRepository; use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -18,11 +17,6 @@ class AuthenticateKey */ private $auth; - /** - * @var \Illuminate\Contracts\Config\Repository - */ - private $config; - /** * @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface */ @@ -33,15 +27,12 @@ class AuthenticateKey * * @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository * @param \Illuminate\Auth\AuthManager $auth - * @param \Illuminate\Contracts\Config\Repository $config */ public function __construct( ApiKeyRepositoryInterface $repository, - AuthManager $auth, - ConfigRepository $config + AuthManager $auth ) { $this->auth = $auth; - $this->config = $config; $this->repository = $repository; } @@ -53,6 +44,9 @@ class AuthenticateKey * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed + * + * @throws \Symfony\Component\HttpKernel\Exception\HttpException + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function handle(Request $request, Closure $next) { diff --git a/tests/Unit/Http/Middleware/API/AuthenticateIPAccessTest.php b/tests/Unit/Http/Middleware/API/AuthenticateIPAccessTest.php new file mode 100644 index 000000000..cd122f7cb --- /dev/null +++ b/tests/Unit/Http/Middleware/API/AuthenticateIPAccessTest.php @@ -0,0 +1,82 @@ +make(['allowed_ips' => []]); + $this->setRequestAttribute('api_key', $model); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Test middleware works correctly when a valid IP accesses + * and there is an IP restriction. + */ + public function testWithValidIP() + { + $model = factory(APIKey::class)->make(['allowed_ips' => ['127.0.0.1']]); + $this->setRequestAttribute('api_key', $model); + + $this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('127.0.0.1'); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Test that a CIDR range can be used. + */ + public function testValidIPAganistCIDRRange() + { + $model = factory(APIKey::class)->make(['allowed_ips' => ['192.168.1.1/28']]); + $this->setRequestAttribute('api_key', $model); + + $this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('192.168.1.15'); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Test that an exception is thrown when an invalid IP address + * tries to connect and there is an IP restriction. + * + * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + */ + public function testWithInvalidIP() + { + $model = factory(APIKey::class)->make(['allowed_ips' => ['127.0.0.1']]); + $this->setRequestAttribute('api_key', $model); + + $this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('127.0.0.2'); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Return an instance of the middleware to be used when testing. + * + * @return \Pterodactyl\Http\Middleware\API\AuthenticateIPAccess + */ + private function getMiddleware(): AuthenticateIPAccess + { + return new AuthenticateIPAccess(); + } +} diff --git a/tests/Unit/Http/Middleware/API/AuthenticateKeyTest.php b/tests/Unit/Http/Middleware/API/AuthenticateKeyTest.php new file mode 100644 index 000000000..e2032b588 --- /dev/null +++ b/tests/Unit/Http/Middleware/API/AuthenticateKeyTest.php @@ -0,0 +1,90 @@ +auth = m::mock(AuthManager::class); + $this->repository = m::mock(ApiKeyRepositoryInterface::class); + } + + /** + * Test that a missing bearer token will throw an exception. + */ + public function testMissingBearerTokenThrowsException() + { + $this->request->shouldReceive('bearerToken')->withNoArgs()->once()->andReturnNull(); + + try { + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } catch (HttpException $exception) { + $this->assertEquals(401, $exception->getStatusCode()); + $this->assertEquals(['WWW-Authenticate' => 'Bearer'], $exception->getHeaders()); + } + } + + /** + * Test that an invalid API token throws an exception. + * + * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + */ + public function testInvalidTokenThrowsException() + { + $this->request->shouldReceive('bearerToken')->withNoArgs()->twice()->andReturn('abcd1234'); + $this->repository->shouldReceive('findFirstWhere')->andThrow(new RecordNotFoundException); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Test that a valid token can continue past the middleware. + */ + public function testValidToken() + { + $model = factory(APIKey::class)->make(); + + $this->request->shouldReceive('bearerToken')->withNoArgs()->twice()->andReturn($model->token); + $this->repository->shouldReceive('findFirstWhere')->with([['token', '=', $model->token]])->once()->andReturn($model); + + $this->auth->shouldReceive('guard->loginUsingId')->with($model->user_id)->once()->andReturnNull(); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + $this->assertEquals($model, $this->request->attributes->get('api_key')); + } + + /** + * Return an instance of the middleware with mocked dependencies for testing. + * + * @return \Pterodactyl\Http\Middleware\API\AuthenticateKey + */ + private function getMiddleware(): AuthenticateKey + { + return new AuthenticateKey($this->repository, $this->auth); + } +} diff --git a/tests/Unit/Http/Middleware/API/SetSessionDriverTest.php b/tests/Unit/Http/Middleware/API/SetSessionDriverTest.php new file mode 100644 index 000000000..dd9fa3e04 --- /dev/null +++ b/tests/Unit/Http/Middleware/API/SetSessionDriverTest.php @@ -0,0 +1,69 @@ +appMock = m::mock(Application::class); + $this->config = m::mock(Repository::class); + } + + /** + * Test that a production environment does not try to disable debug bar. + */ + public function testProductionEnvironment() + { + $this->appMock->shouldReceive('environment')->withNoArgs()->once()->andReturn('production'); + $this->config->shouldReceive('set')->with('session.driver', 'array')->once()->andReturnNull(); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Test that a local environment does disable debug bar. + */ + public function testLocalEnvironment() + { + $this->appMock->shouldReceive('environment')->withNoArgs()->once()->andReturn('local'); + $this->appMock->shouldReceive('make')->with(LaravelDebugbar::class)->once()->andReturnSelf(); + $this->appMock->shouldReceive('disable')->withNoArgs()->once()->andReturnNull(); + + $this->config->shouldReceive('set')->with('session.driver', 'array')->once()->andReturnNull(); + + $this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); + } + + /** + * Return an instance of the middleware with mocked dependencies for testing. + * + * @return \Pterodactyl\Http\Middleware\API\SetSessionDriver + */ + private function getMiddleware(): SetSessionDriver + { + return new SetSessionDriver($this->appMock, $this->config); + } +}