]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/api/ApiMiddlewareTest.php
Merge pull request #1575 from ArthurHoaro/feature/php8
[github/shaarli/Shaarli.git] / tests / api / ApiMiddlewareTest.php
1 <?php
2 namespace Shaarli\Api;
3
4 use Shaarli\Config\ConfigManager;
5 use Shaarli\History;
6 use Slim\Container;
7 use Slim\Http\Environment;
8 use Slim\Http\Request;
9 use Slim\Http\Response;
10
11 /**
12 * Class ApiMiddlewareTest
13 *
14 * Test the REST API Slim Middleware.
15 *
16 * Note that we can't test a valid use case here, because the middleware
17 * needs to call a valid controller/action during its execution.
18 *
19 * @package Api
20 */
21 class ApiMiddlewareTest extends \Shaarli\TestCase
22 {
23 /**
24 * @var string datastore to test write operations
25 */
26 protected static $testDatastore = 'sandbox/datastore.php';
27
28 /**
29 * @var ConfigManager instance
30 */
31 protected $conf;
32
33 /**
34 * @var \ReferenceLinkDB instance.
35 */
36 protected $refDB = null;
37
38 /**
39 * @var Container instance.
40 */
41 protected $container;
42
43 /**
44 * Before every test, instantiate a new Api with its config, plugins and bookmarks.
45 */
46 protected function setUp(): void
47 {
48 $this->conf = new ConfigManager('tests/utils/config/configJson');
49 $this->conf->set('api.secret', 'NapoleonWasALizard');
50
51 $this->refDB = new \ReferenceLinkDB();
52 $this->refDB->write(self::$testDatastore);
53
54 $history = new History('sandbox/history.php');
55
56 $this->container = new Container();
57 $this->container['conf'] = $this->conf;
58 $this->container['history'] = $history;
59 }
60
61 /**
62 * After every test, remove the test datastore.
63 */
64 protected function tearDown(): void
65 {
66 @unlink(self::$testDatastore);
67 }
68
69 /**
70 * Invoke the middleware with a valid token
71 */
72 public function testInvokeMiddlewareWithValidToken(): void
73 {
74 $next = function (Request $request, Response $response): Response {
75 return $response;
76 };
77 $mw = new ApiMiddleware($this->container);
78 $env = Environment::mock([
79 'REQUEST_METHOD' => 'GET',
80 'REQUEST_URI' => '/echo',
81 'HTTP_AUTHORIZATION'=> 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard'),
82 ]);
83 $request = Request::createFromEnvironment($env);
84 $response = new Response();
85 /** @var Response $response */
86 $response = $mw($request, $response, $next);
87
88 $this->assertEquals(200, $response->getStatusCode());
89 }
90
91 /**
92 * Invoke the middleware with a valid token
93 * Using specific Apache CGI redirected authorization.
94 */
95 public function testInvokeMiddlewareWithValidTokenFromRedirectedHeader(): void
96 {
97 $next = function (Request $request, Response $response): Response {
98 return $response;
99 };
100
101 $token = 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard');
102 $this->container->environment['REDIRECT_HTTP_AUTHORIZATION'] = $token;
103 $mw = new ApiMiddleware($this->container);
104 $env = Environment::mock([
105 'REQUEST_METHOD' => 'GET',
106 'REQUEST_URI' => '/echo',
107 ]);
108 $request = Request::createFromEnvironment($env);
109 $response = new Response();
110 /** @var Response $response */
111 $response = $mw($request, $response, $next);
112
113 $this->assertEquals(200, $response->getStatusCode());
114 }
115
116 /**
117 * Invoke the middleware with the API disabled:
118 * should return a 401 error Unauthorized.
119 */
120 public function testInvokeMiddlewareApiDisabled()
121 {
122 $this->conf->set('api.enabled', false);
123 $mw = new ApiMiddleware($this->container);
124 $env = Environment::mock([
125 'REQUEST_METHOD' => 'GET',
126 'REQUEST_URI' => '/echo',
127 ]);
128 $request = Request::createFromEnvironment($env);
129 $response = new Response();
130 /** @var Response $response */
131 $response = $mw($request, $response, null);
132
133 $this->assertEquals(401, $response->getStatusCode());
134 $body = json_decode((string) $response->getBody());
135 $this->assertEquals('Not authorized', $body);
136 }
137
138 /**
139 * Invoke the middleware with the API disabled in debug mode:
140 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
141 */
142 public function testInvokeMiddlewareApiDisabledDebug()
143 {
144 $this->conf->set('api.enabled', false);
145 $this->conf->set('dev.debug', true);
146 $mw = new ApiMiddleware($this->container);
147 $env = Environment::mock([
148 'REQUEST_METHOD' => 'GET',
149 'REQUEST_URI' => '/echo',
150 ]);
151 $request = Request::createFromEnvironment($env);
152 $response = new Response();
153 /** @var Response $response */
154 $response = $mw($request, $response, null);
155
156 $this->assertEquals(401, $response->getStatusCode());
157 $body = json_decode((string) $response->getBody());
158 $this->assertEquals('Not authorized: API is disabled', $body->message);
159 $this->assertContainsPolyfill('ApiAuthorizationException', $body->stacktrace);
160 }
161
162 /**
163 * Invoke the middleware without a token (debug):
164 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
165 */
166 public function testInvokeMiddlewareNoTokenProvidedDebug()
167 {
168 $this->conf->set('dev.debug', true);
169 $mw = new ApiMiddleware($this->container);
170 $env = Environment::mock([
171 'REQUEST_METHOD' => 'GET',
172 'REQUEST_URI' => '/echo',
173 ]);
174 $request = Request::createFromEnvironment($env);
175 $response = new Response();
176 /** @var Response $response */
177 $response = $mw($request, $response, null);
178
179 $this->assertEquals(401, $response->getStatusCode());
180 $body = json_decode((string) $response->getBody());
181 $this->assertEquals('Not authorized: JWT token not provided', $body->message);
182 $this->assertContainsPolyfill('ApiAuthorizationException', $body->stacktrace);
183 }
184
185 /**
186 * Invoke the middleware without a secret set in settings (debug):
187 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
188 */
189 public function testInvokeMiddlewareNoSecretSetDebug()
190 {
191 $this->conf->set('dev.debug', true);
192 $this->conf->set('api.secret', '');
193 $mw = new ApiMiddleware($this->container);
194 $env = Environment::mock([
195 'REQUEST_METHOD' => 'GET',
196 'REQUEST_URI' => '/echo',
197 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
198 ]);
199 $request = Request::createFromEnvironment($env);
200 $response = new Response();
201 /** @var Response $response */
202 $response = $mw($request, $response, null);
203
204 $this->assertEquals(401, $response->getStatusCode());
205 $body = json_decode((string) $response->getBody());
206 $this->assertEquals('Not authorized: Token secret must be set in Shaarli\'s administration', $body->message);
207 $this->assertContainsPolyfill('ApiAuthorizationException', $body->stacktrace);
208 }
209
210 /**
211 * Invoke the middleware with an invalid JWT token header
212 */
213 public function testInvalidJwtAuthHeaderDebug()
214 {
215 $this->conf->set('dev.debug', true);
216 $mw = new ApiMiddleware($this->container);
217 $env = Environment::mock([
218 'REQUEST_METHOD' => 'GET',
219 'REQUEST_URI' => '/echo',
220 'HTTP_AUTHORIZATION'=> 'PolarBearer jwt',
221 ]);
222 $request = Request::createFromEnvironment($env);
223 $response = new Response();
224 /** @var Response $response */
225 $response = $mw($request, $response, null);
226
227 $this->assertEquals(401, $response->getStatusCode());
228 $body = json_decode((string) $response->getBody());
229 $this->assertEquals('Not authorized: Invalid JWT header', $body->message);
230 $this->assertContainsPolyfill('ApiAuthorizationException', $body->stacktrace);
231 }
232
233 /**
234 * Invoke the middleware with an invalid JWT token (debug):
235 * should return a 401 error Unauthorized - with a specific message and a stacktrace.
236 *
237 * Note: specific JWT errors tests are handled in ApiUtilsTest.
238 */
239 public function testInvokeMiddlewareInvalidJwtDebug()
240 {
241 $this->conf->set('dev.debug', true);
242 $mw = new ApiMiddleware($this->container);
243 $env = Environment::mock([
244 'REQUEST_METHOD' => 'GET',
245 'REQUEST_URI' => '/echo',
246 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
247 ]);
248 $request = Request::createFromEnvironment($env);
249 $response = new Response();
250 /** @var Response $response */
251 $response = $mw($request, $response, null);
252
253 $this->assertEquals(401, $response->getStatusCode());
254 $body = json_decode((string) $response->getBody());
255 $this->assertEquals('Not authorized: Malformed JWT token', $body->message);
256 $this->assertContainsPolyfill('ApiAuthorizationException', $body->stacktrace);
257 }
258 }