Skip to content

Commit 49379bd

Browse files
committed
Pop some tests for new middleware in there.
1 parent 45a1534 commit 49379bd

File tree

4 files changed

+245
-10
lines changed

4 files changed

+245
-10
lines changed

app/Http/Middleware/API/AuthenticateKey.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Illuminate\Auth\AuthManager;
88
use Symfony\Component\HttpKernel\Exception\HttpException;
99
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
10-
use Illuminate\Contracts\Config\Repository as ConfigRepository;
1110
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
1211
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
1312

@@ -18,11 +17,6 @@ class AuthenticateKey
1817
*/
1918
private $auth;
2019

21-
/**
22-
* @var \Illuminate\Contracts\Config\Repository
23-
*/
24-
private $config;
25-
2620
/**
2721
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface
2822
*/
@@ -33,15 +27,12 @@ class AuthenticateKey
3327
*
3428
* @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository
3529
* @param \Illuminate\Auth\AuthManager $auth
36-
* @param \Illuminate\Contracts\Config\Repository $config
3730
*/
3831
public function __construct(
3932
ApiKeyRepositoryInterface $repository,
40-
AuthManager $auth,
41-
ConfigRepository $config
33+
AuthManager $auth
4234
) {
4335
$this->auth = $auth;
44-
$this->config = $config;
4536
$this->repository = $repository;
4637
}
4738

@@ -53,6 +44,9 @@ public function __construct(
5344
* @param \Illuminate\Http\Request $request
5445
* @param \Closure $next
5546
* @return mixed
47+
*
48+
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
49+
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
5650
*/
5751
public function handle(Request $request, Closure $next)
5852
{
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace Tests\Unit\Http\Middleware\API;
4+
5+
use Pterodactyl\Models\APIKey;
6+
use Tests\Unit\Http\Middleware\MiddlewareTestCase;
7+
use Pterodactyl\Http\Middleware\API\AuthenticateIPAccess;
8+
9+
class AuthenticateIPAccessTest extends MiddlewareTestCase
10+
{
11+
/**
12+
* Setup tests.
13+
*/
14+
public function setUp()
15+
{
16+
parent::setUp();
17+
}
18+
19+
/**
20+
* Test middleware when there are no IP restrictions.
21+
*/
22+
public function testWithNoIPRestrictions()
23+
{
24+
$model = factory(APIKey::class)->make(['allowed_ips' => []]);
25+
$this->setRequestAttribute('api_key', $model);
26+
27+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
28+
}
29+
30+
/**
31+
* Test middleware works correctly when a valid IP accesses
32+
* and there is an IP restriction.
33+
*/
34+
public function testWithValidIP()
35+
{
36+
$model = factory(APIKey::class)->make(['allowed_ips' => ['127.0.0.1']]);
37+
$this->setRequestAttribute('api_key', $model);
38+
39+
$this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('127.0.0.1');
40+
41+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
42+
}
43+
44+
/**
45+
* Test that a CIDR range can be used.
46+
*/
47+
public function testValidIPAganistCIDRRange()
48+
{
49+
$model = factory(APIKey::class)->make(['allowed_ips' => ['192.168.1.1/28']]);
50+
$this->setRequestAttribute('api_key', $model);
51+
52+
$this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('192.168.1.15');
53+
54+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
55+
}
56+
57+
/**
58+
* Test that an exception is thrown when an invalid IP address
59+
* tries to connect and there is an IP restriction.
60+
*
61+
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
62+
*/
63+
public function testWithInvalidIP()
64+
{
65+
$model = factory(APIKey::class)->make(['allowed_ips' => ['127.0.0.1']]);
66+
$this->setRequestAttribute('api_key', $model);
67+
68+
$this->request->shouldReceive('ip')->withNoArgs()->once()->andReturn('127.0.0.2');
69+
70+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
71+
}
72+
73+
/**
74+
* Return an instance of the middleware to be used when testing.
75+
*
76+
* @return \Pterodactyl\Http\Middleware\API\AuthenticateIPAccess
77+
*/
78+
private function getMiddleware(): AuthenticateIPAccess
79+
{
80+
return new AuthenticateIPAccess();
81+
}
82+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Tests\Unit\Http\Middleware\API;
4+
5+
use Mockery as m;
6+
use Pterodactyl\Models\APIKey;
7+
use Illuminate\Auth\AuthManager;
8+
use Tests\Unit\Http\Middleware\MiddlewareTestCase;
9+
use Pterodactyl\Http\Middleware\API\AuthenticateKey;
10+
use Symfony\Component\HttpKernel\Exception\HttpException;
11+
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
12+
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
13+
14+
class AuthenticateKeyTest extends MiddlewareTestCase
15+
{
16+
/**
17+
* @var \Illuminate\Auth\AuthManager|\Mockery\Mock
18+
*/
19+
private $auth;
20+
21+
/**
22+
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface|\Mockery\Mock
23+
*/
24+
private $repository;
25+
26+
/**
27+
* Setup tests.
28+
*/
29+
public function setUp()
30+
{
31+
parent::setUp();
32+
33+
$this->auth = m::mock(AuthManager::class);
34+
$this->repository = m::mock(ApiKeyRepositoryInterface::class);
35+
}
36+
37+
/**
38+
* Test that a missing bearer token will throw an exception.
39+
*/
40+
public function testMissingBearerTokenThrowsException()
41+
{
42+
$this->request->shouldReceive('bearerToken')->withNoArgs()->once()->andReturnNull();
43+
44+
try {
45+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
46+
} catch (HttpException $exception) {
47+
$this->assertEquals(401, $exception->getStatusCode());
48+
$this->assertEquals(['WWW-Authenticate' => 'Bearer'], $exception->getHeaders());
49+
}
50+
}
51+
52+
/**
53+
* Test that an invalid API token throws an exception.
54+
*
55+
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
56+
*/
57+
public function testInvalidTokenThrowsException()
58+
{
59+
$this->request->shouldReceive('bearerToken')->withNoArgs()->twice()->andReturn('abcd1234');
60+
$this->repository->shouldReceive('findFirstWhere')->andThrow(new RecordNotFoundException);
61+
62+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
63+
}
64+
65+
/**
66+
* Test that a valid token can continue past the middleware.
67+
*/
68+
public function testValidToken()
69+
{
70+
$model = factory(APIKey::class)->make();
71+
72+
$this->request->shouldReceive('bearerToken')->withNoArgs()->twice()->andReturn($model->token);
73+
$this->repository->shouldReceive('findFirstWhere')->with([['token', '=', $model->token]])->once()->andReturn($model);
74+
75+
$this->auth->shouldReceive('guard->loginUsingId')->with($model->user_id)->once()->andReturnNull();
76+
77+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
78+
$this->assertEquals($model, $this->request->attributes->get('api_key'));
79+
}
80+
81+
/**
82+
* Return an instance of the middleware with mocked dependencies for testing.
83+
*
84+
* @return \Pterodactyl\Http\Middleware\API\AuthenticateKey
85+
*/
86+
private function getMiddleware(): AuthenticateKey
87+
{
88+
return new AuthenticateKey($this->repository, $this->auth);
89+
}
90+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Tests\Unit\Http\Middleware\API;
4+
5+
use Mockery as m;
6+
use Barryvdh\Debugbar\LaravelDebugbar;
7+
use Illuminate\Contracts\Config\Repository;
8+
use Illuminate\Contracts\Foundation\Application;
9+
use Tests\Unit\Http\Middleware\MiddlewareTestCase;
10+
use Pterodactyl\Http\Middleware\API\SetSessionDriver;
11+
12+
class SetSessionDriverTest extends MiddlewareTestCase
13+
{
14+
/**
15+
* @var \Illuminate\Contracts\Foundation\Application|\Mockery\Mock
16+
*/
17+
private $appMock;
18+
19+
/**
20+
* @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock
21+
*/
22+
private $config;
23+
24+
/**
25+
* Setup tests.
26+
*/
27+
public function setUp()
28+
{
29+
parent::setUp();
30+
31+
$this->appMock = m::mock(Application::class);
32+
$this->config = m::mock(Repository::class);
33+
}
34+
35+
/**
36+
* Test that a production environment does not try to disable debug bar.
37+
*/
38+
public function testProductionEnvironment()
39+
{
40+
$this->appMock->shouldReceive('environment')->withNoArgs()->once()->andReturn('production');
41+
$this->config->shouldReceive('set')->with('session.driver', 'array')->once()->andReturnNull();
42+
43+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
44+
}
45+
46+
/**
47+
* Test that a local environment does disable debug bar.
48+
*/
49+
public function testLocalEnvironment()
50+
{
51+
$this->appMock->shouldReceive('environment')->withNoArgs()->once()->andReturn('local');
52+
$this->appMock->shouldReceive('make')->with(LaravelDebugbar::class)->once()->andReturnSelf();
53+
$this->appMock->shouldReceive('disable')->withNoArgs()->once()->andReturnNull();
54+
55+
$this->config->shouldReceive('set')->with('session.driver', 'array')->once()->andReturnNull();
56+
57+
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
58+
}
59+
60+
/**
61+
* Return an instance of the middleware with mocked dependencies for testing.
62+
*
63+
* @return \Pterodactyl\Http\Middleware\API\SetSessionDriver
64+
*/
65+
private function getMiddleware(): SetSessionDriver
66+
{
67+
return new SetSessionDriver($this->appMock, $this->config);
68+
}
69+
}

0 commit comments

Comments
 (0)