diff options
Diffstat (limited to 'tests/api/ApiUtilsTest.php')
-rw-r--r-- | tests/api/ApiUtilsTest.php | 145 |
1 files changed, 74 insertions, 71 deletions
diff --git a/tests/api/ApiUtilsTest.php b/tests/api/ApiUtilsTest.php index ea0ae500..7a143859 100644 --- a/tests/api/ApiUtilsTest.php +++ b/tests/api/ApiUtilsTest.php | |||
@@ -2,17 +2,18 @@ | |||
2 | 2 | ||
3 | namespace Shaarli\Api; | 3 | namespace Shaarli\Api; |
4 | 4 | ||
5 | use Shaarli\Bookmark\Bookmark; | ||
5 | use Shaarli\Http\Base64Url; | 6 | use Shaarli\Http\Base64Url; |
6 | 7 | ||
7 | /** | 8 | /** |
8 | * Class ApiUtilsTest | 9 | * Class ApiUtilsTest |
9 | */ | 10 | */ |
10 | class ApiUtilsTest extends \PHPUnit\Framework\TestCase | 11 | class ApiUtilsTest extends \Shaarli\TestCase |
11 | { | 12 | { |
12 | /** | 13 | /** |
13 | * Force the timezone for ISO datetimes. | 14 | * Force the timezone for ISO datetimes. |
14 | */ | 15 | */ |
15 | public static function setUpBeforeClass() | 16 | public static function setUpBeforeClass(): void |
16 | { | 17 | { |
17 | date_default_timezone_set('UTC'); | 18 | date_default_timezone_set('UTC'); |
18 | } | 19 | } |
@@ -60,148 +61,148 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
60 | public function testValidateJwtTokenValid() | 61 | public function testValidateJwtTokenValid() |
61 | { | 62 | { |
62 | $secret = 'WarIsPeace'; | 63 | $secret = 'WarIsPeace'; |
63 | ApiUtils::validateJwtToken(self::generateValidJwtToken($secret), $secret); | 64 | $this->assertTrue(ApiUtils::validateJwtToken(self::generateValidJwtToken($secret), $secret)); |
64 | } | 65 | } |
65 | 66 | ||
66 | /** | 67 | /** |
67 | * Test validateJwtToken() with a malformed JWT token. | 68 | * Test validateJwtToken() with a malformed JWT token. |
68 | * | ||
69 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
70 | * @expectedExceptionMessage Malformed JWT token | ||
71 | */ | 69 | */ |
72 | public function testValidateJwtTokenMalformed() | 70 | public function testValidateJwtTokenMalformed() |
73 | { | 71 | { |
72 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
73 | $this->expectExceptionMessage('Malformed JWT token'); | ||
74 | |||
74 | $token = 'ABC.DEF'; | 75 | $token = 'ABC.DEF'; |
75 | ApiUtils::validateJwtToken($token, 'foo'); | 76 | ApiUtils::validateJwtToken($token, 'foo'); |
76 | } | 77 | } |
77 | 78 | ||
78 | /** | 79 | /** |
79 | * Test validateJwtToken() with an empty JWT token. | 80 | * Test validateJwtToken() with an empty JWT token. |
80 | * | ||
81 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
82 | * @expectedExceptionMessage Malformed JWT token | ||
83 | */ | 81 | */ |
84 | public function testValidateJwtTokenMalformedEmpty() | 82 | public function testValidateJwtTokenMalformedEmpty() |
85 | { | 83 | { |
84 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
85 | $this->expectExceptionMessage('Malformed JWT token'); | ||
86 | |||
86 | $token = false; | 87 | $token = false; |
87 | ApiUtils::validateJwtToken($token, 'foo'); | 88 | ApiUtils::validateJwtToken($token, 'foo'); |
88 | } | 89 | } |
89 | 90 | ||
90 | /** | 91 | /** |
91 | * Test validateJwtToken() with a JWT token without header. | 92 | * Test validateJwtToken() with a JWT token without header. |
92 | * | ||
93 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
94 | * @expectedExceptionMessage Malformed JWT token | ||
95 | */ | 93 | */ |
96 | public function testValidateJwtTokenMalformedEmptyHeader() | 94 | public function testValidateJwtTokenMalformedEmptyHeader() |
97 | { | 95 | { |
96 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
97 | $this->expectExceptionMessage('Malformed JWT token'); | ||
98 | |||
98 | $token = '.payload.signature'; | 99 | $token = '.payload.signature'; |
99 | ApiUtils::validateJwtToken($token, 'foo'); | 100 | ApiUtils::validateJwtToken($token, 'foo'); |
100 | } | 101 | } |
101 | 102 | ||
102 | /** | 103 | /** |
103 | * Test validateJwtToken() with a JWT token without payload | 104 | * Test validateJwtToken() with a JWT token without payload |
104 | * | ||
105 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
106 | * @expectedExceptionMessage Malformed JWT token | ||
107 | */ | 105 | */ |
108 | public function testValidateJwtTokenMalformedEmptyPayload() | 106 | public function testValidateJwtTokenMalformedEmptyPayload() |
109 | { | 107 | { |
108 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
109 | $this->expectExceptionMessage('Malformed JWT token'); | ||
110 | |||
110 | $token = 'header..signature'; | 111 | $token = 'header..signature'; |
111 | ApiUtils::validateJwtToken($token, 'foo'); | 112 | ApiUtils::validateJwtToken($token, 'foo'); |
112 | } | 113 | } |
113 | 114 | ||
114 | /** | 115 | /** |
115 | * Test validateJwtToken() with a JWT token with an empty signature. | 116 | * Test validateJwtToken() with a JWT token with an empty signature. |
116 | * | ||
117 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
118 | * @expectedExceptionMessage Invalid JWT signature | ||
119 | */ | 117 | */ |
120 | public function testValidateJwtTokenInvalidSignatureEmpty() | 118 | public function testValidateJwtTokenInvalidSignatureEmpty() |
121 | { | 119 | { |
120 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
121 | $this->expectExceptionMessage('Invalid JWT signature'); | ||
122 | |||
122 | $token = 'header.payload.'; | 123 | $token = 'header.payload.'; |
123 | ApiUtils::validateJwtToken($token, 'foo'); | 124 | ApiUtils::validateJwtToken($token, 'foo'); |
124 | } | 125 | } |
125 | 126 | ||
126 | /** | 127 | /** |
127 | * Test validateJwtToken() with a JWT token with an invalid signature. | 128 | * Test validateJwtToken() with a JWT token with an invalid signature. |
128 | * | ||
129 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
130 | * @expectedExceptionMessage Invalid JWT signature | ||
131 | */ | 129 | */ |
132 | public function testValidateJwtTokenInvalidSignature() | 130 | public function testValidateJwtTokenInvalidSignature() |
133 | { | 131 | { |
132 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
133 | $this->expectExceptionMessage('Invalid JWT signature'); | ||
134 | |||
134 | $token = 'header.payload.nope'; | 135 | $token = 'header.payload.nope'; |
135 | ApiUtils::validateJwtToken($token, 'foo'); | 136 | ApiUtils::validateJwtToken($token, 'foo'); |
136 | } | 137 | } |
137 | 138 | ||
138 | /** | 139 | /** |
139 | * Test validateJwtToken() with a JWT token with a signature generated with the wrong API secret. | 140 | * Test validateJwtToken() with a JWT token with a signature generated with the wrong API secret. |
140 | * | ||
141 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
142 | * @expectedExceptionMessage Invalid JWT signature | ||
143 | */ | 141 | */ |
144 | public function testValidateJwtTokenInvalidSignatureSecret() | 142 | public function testValidateJwtTokenInvalidSignatureSecret() |
145 | { | 143 | { |
144 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
145 | $this->expectExceptionMessage('Invalid JWT signature'); | ||
146 | |||
146 | ApiUtils::validateJwtToken(self::generateValidJwtToken('foo'), 'bar'); | 147 | ApiUtils::validateJwtToken(self::generateValidJwtToken('foo'), 'bar'); |
147 | } | 148 | } |
148 | 149 | ||
149 | /** | 150 | /** |
150 | * Test validateJwtToken() with a JWT token with a an invalid header (not JSON). | 151 | * Test validateJwtToken() with a JWT token with a an invalid header (not JSON). |
151 | * | ||
152 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
153 | * @expectedExceptionMessage Invalid JWT header | ||
154 | */ | 152 | */ |
155 | public function testValidateJwtTokenInvalidHeader() | 153 | public function testValidateJwtTokenInvalidHeader() |
156 | { | 154 | { |
155 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
156 | $this->expectExceptionMessage('Invalid JWT header'); | ||
157 | |||
157 | $token = $this->generateCustomJwtToken('notJSON', '{"JSON":1}', 'secret'); | 158 | $token = $this->generateCustomJwtToken('notJSON', '{"JSON":1}', 'secret'); |
158 | ApiUtils::validateJwtToken($token, 'secret'); | 159 | ApiUtils::validateJwtToken($token, 'secret'); |
159 | } | 160 | } |
160 | 161 | ||
161 | /** | 162 | /** |
162 | * Test validateJwtToken() with a JWT token with a an invalid payload (not JSON). | 163 | * Test validateJwtToken() with a JWT token with a an invalid payload (not JSON). |
163 | * | ||
164 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
165 | * @expectedExceptionMessage Invalid JWT payload | ||
166 | */ | 164 | */ |
167 | public function testValidateJwtTokenInvalidPayload() | 165 | public function testValidateJwtTokenInvalidPayload() |
168 | { | 166 | { |
167 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
168 | $this->expectExceptionMessage('Invalid JWT payload'); | ||
169 | |||
169 | $token = $this->generateCustomJwtToken('{"JSON":1}', 'notJSON', 'secret'); | 170 | $token = $this->generateCustomJwtToken('{"JSON":1}', 'notJSON', 'secret'); |
170 | ApiUtils::validateJwtToken($token, 'secret'); | 171 | ApiUtils::validateJwtToken($token, 'secret'); |
171 | } | 172 | } |
172 | 173 | ||
173 | /** | 174 | /** |
174 | * Test validateJwtToken() with a JWT token without issued time. | 175 | * Test validateJwtToken() with a JWT token without issued time. |
175 | * | ||
176 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
177 | * @expectedExceptionMessage Invalid JWT issued time | ||
178 | */ | 176 | */ |
179 | public function testValidateJwtTokenInvalidTimeEmpty() | 177 | public function testValidateJwtTokenInvalidTimeEmpty() |
180 | { | 178 | { |
179 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
180 | $this->expectExceptionMessage('Invalid JWT issued time'); | ||
181 | |||
181 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"JSON":1}', 'secret'); | 182 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"JSON":1}', 'secret'); |
182 | ApiUtils::validateJwtToken($token, 'secret'); | 183 | ApiUtils::validateJwtToken($token, 'secret'); |
183 | } | 184 | } |
184 | 185 | ||
185 | /** | 186 | /** |
186 | * Test validateJwtToken() with an expired JWT token. | 187 | * Test validateJwtToken() with an expired JWT token. |
187 | * | ||
188 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
189 | * @expectedExceptionMessage Invalid JWT issued time | ||
190 | */ | 188 | */ |
191 | public function testValidateJwtTokenInvalidTimeExpired() | 189 | public function testValidateJwtTokenInvalidTimeExpired() |
192 | { | 190 | { |
191 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
192 | $this->expectExceptionMessage('Invalid JWT issued time'); | ||
193 | |||
193 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() - 600) . '}', 'secret'); | 194 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() - 600) . '}', 'secret'); |
194 | ApiUtils::validateJwtToken($token, 'secret'); | 195 | ApiUtils::validateJwtToken($token, 'secret'); |
195 | } | 196 | } |
196 | 197 | ||
197 | /** | 198 | /** |
198 | * Test validateJwtToken() with a JWT token issued in the future. | 199 | * Test validateJwtToken() with a JWT token issued in the future. |
199 | * | ||
200 | * @expectedException \Shaarli\Api\Exceptions\ApiAuthorizationException | ||
201 | * @expectedExceptionMessage Invalid JWT issued time | ||
202 | */ | 200 | */ |
203 | public function testValidateJwtTokenInvalidTimeFuture() | 201 | public function testValidateJwtTokenInvalidTimeFuture() |
204 | { | 202 | { |
203 | $this->expectException(\Shaarli\Api\Exceptions\ApiAuthorizationException::class); | ||
204 | $this->expectExceptionMessage('Invalid JWT issued time'); | ||
205 | |||
205 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() + 60) . '}', 'secret'); | 206 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() + 60) . '}', 'secret'); |
206 | ApiUtils::validateJwtToken($token, 'secret'); | 207 | ApiUtils::validateJwtToken($token, 'secret'); |
207 | } | 208 | } |
@@ -212,7 +213,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
212 | public function testFormatLinkComplete() | 213 | public function testFormatLinkComplete() |
213 | { | 214 | { |
214 | $indexUrl = 'https://domain.tld/sub/'; | 215 | $indexUrl = 'https://domain.tld/sub/'; |
215 | $link = [ | 216 | $data = [ |
216 | 'id' => 12, | 217 | 'id' => 12, |
217 | 'url' => 'http://lol.lol', | 218 | 'url' => 'http://lol.lol', |
218 | 'shorturl' => 'abc', | 219 | 'shorturl' => 'abc', |
@@ -223,6 +224,8 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
223 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), | 224 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), |
224 | 'updated' => \DateTime::createFromFormat('Ymd_His', '20170107_160612'), | 225 | 'updated' => \DateTime::createFromFormat('Ymd_His', '20170107_160612'), |
225 | ]; | 226 | ]; |
227 | $bookmark = new Bookmark(); | ||
228 | $bookmark->fromArray($data); | ||
226 | 229 | ||
227 | $expected = [ | 230 | $expected = [ |
228 | 'id' => 12, | 231 | 'id' => 12, |
@@ -236,7 +239,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
236 | 'updated' => '2017-01-07T16:06:12+00:00', | 239 | 'updated' => '2017-01-07T16:06:12+00:00', |
237 | ]; | 240 | ]; |
238 | 241 | ||
239 | $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl)); | 242 | $this->assertEquals($expected, ApiUtils::formatLink($bookmark, $indexUrl)); |
240 | } | 243 | } |
241 | 244 | ||
242 | /** | 245 | /** |
@@ -245,7 +248,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
245 | public function testFormatLinkMinimalNote() | 248 | public function testFormatLinkMinimalNote() |
246 | { | 249 | { |
247 | $indexUrl = 'https://domain.tld/sub/'; | 250 | $indexUrl = 'https://domain.tld/sub/'; |
248 | $link = [ | 251 | $data = [ |
249 | 'id' => 12, | 252 | 'id' => 12, |
250 | 'url' => '?abc', | 253 | 'url' => '?abc', |
251 | 'shorturl' => 'abc', | 254 | 'shorturl' => 'abc', |
@@ -255,6 +258,8 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
255 | 'private' => '', | 258 | 'private' => '', |
256 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), | 259 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), |
257 | ]; | 260 | ]; |
261 | $bookmark = new Bookmark(); | ||
262 | $bookmark->fromArray($data); | ||
258 | 263 | ||
259 | $expected = [ | 264 | $expected = [ |
260 | 'id' => 12, | 265 | 'id' => 12, |
@@ -268,7 +273,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
268 | 'updated' => '', | 273 | 'updated' => '', |
269 | ]; | 274 | ]; |
270 | 275 | ||
271 | $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl)); | 276 | $this->assertEquals($expected, ApiUtils::formatLink($bookmark, $indexUrl)); |
272 | } | 277 | } |
273 | 278 | ||
274 | /** | 279 | /** |
@@ -277,7 +282,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
277 | public function testUpdateLink() | 282 | public function testUpdateLink() |
278 | { | 283 | { |
279 | $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102'); | 284 | $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102'); |
280 | $old = [ | 285 | $data = [ |
281 | 'id' => 12, | 286 | 'id' => 12, |
282 | 'url' => '?abc', | 287 | 'url' => '?abc', |
283 | 'shorturl' => 'abc', | 288 | 'shorturl' => 'abc', |
@@ -287,8 +292,10 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
287 | 'private' => '', | 292 | 'private' => '', |
288 | 'created' => $created, | 293 | 'created' => $created, |
289 | ]; | 294 | ]; |
295 | $old = new Bookmark(); | ||
296 | $old->fromArray($data); | ||
290 | 297 | ||
291 | $new = [ | 298 | $data = [ |
292 | 'id' => 13, | 299 | 'id' => 13, |
293 | 'shorturl' => 'nope', | 300 | 'shorturl' => 'nope', |
294 | 'url' => 'http://somewhere.else', | 301 | 'url' => 'http://somewhere.else', |
@@ -299,17 +306,18 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
299 | 'created' => 'creation', | 306 | 'created' => 'creation', |
300 | 'updated' => 'updation', | 307 | 'updated' => 'updation', |
301 | ]; | 308 | ]; |
309 | $new = new Bookmark(); | ||
310 | $new->fromArray($data); | ||
302 | 311 | ||
303 | $result = ApiUtils::updateLink($old, $new); | 312 | $result = ApiUtils::updateLink($old, $new); |
304 | $this->assertEquals(12, $result['id']); | 313 | $this->assertEquals(12, $result->getId()); |
305 | $this->assertEquals('http://somewhere.else', $result['url']); | 314 | $this->assertEquals('http://somewhere.else', $result->getUrl()); |
306 | $this->assertEquals('abc', $result['shorturl']); | 315 | $this->assertEquals('abc', $result->getShortUrl()); |
307 | $this->assertEquals('Le Cid', $result['title']); | 316 | $this->assertEquals('Le Cid', $result->getTitle()); |
308 | $this->assertEquals('Percé jusques au fond du cœur [...]', $result['description']); | 317 | $this->assertEquals('Percé jusques au fond du cœur [...]', $result->getDescription()); |
309 | $this->assertEquals('corneille rodrigue', $result['tags']); | 318 | $this->assertEquals('corneille rodrigue', $result->getTagsString()); |
310 | $this->assertEquals(true, $result['private']); | 319 | $this->assertEquals(true, $result->isPrivate()); |
311 | $this->assertEquals($created, $result['created']); | 320 | $this->assertEquals($created, $result->getCreated()); |
312 | $this->assertTrue(new \DateTime('5 seconds ago') < $result['updated']); | ||
313 | } | 321 | } |
314 | 322 | ||
315 | /** | 323 | /** |
@@ -318,7 +326,7 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
318 | public function testUpdateLinkMinimal() | 326 | public function testUpdateLinkMinimal() |
319 | { | 327 | { |
320 | $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102'); | 328 | $created = \DateTime::createFromFormat('Ymd_His', '20170107_160102'); |
321 | $old = [ | 329 | $data = [ |
322 | 'id' => 12, | 330 | 'id' => 12, |
323 | 'url' => '?abc', | 331 | 'url' => '?abc', |
324 | 'shorturl' => 'abc', | 332 | 'shorturl' => 'abc', |
@@ -328,24 +336,19 @@ class ApiUtilsTest extends \PHPUnit\Framework\TestCase | |||
328 | 'private' => true, | 336 | 'private' => true, |
329 | 'created' => $created, | 337 | 'created' => $created, |
330 | ]; | 338 | ]; |
339 | $old = new Bookmark(); | ||
340 | $old->fromArray($data); | ||
331 | 341 | ||
332 | $new = [ | 342 | $new = new Bookmark(); |
333 | 'url' => '', | ||
334 | 'title' => '', | ||
335 | 'description' => '', | ||
336 | 'tags' => '', | ||
337 | 'private' => false, | ||
338 | ]; | ||
339 | 343 | ||
340 | $result = ApiUtils::updateLink($old, $new); | 344 | $result = ApiUtils::updateLink($old, $new); |
341 | $this->assertEquals(12, $result['id']); | 345 | $this->assertEquals(12, $result->getId()); |
342 | $this->assertEquals('?abc', $result['url']); | 346 | $this->assertEquals('', $result->getUrl()); |
343 | $this->assertEquals('abc', $result['shorturl']); | 347 | $this->assertEquals('abc', $result->getShortUrl()); |
344 | $this->assertEquals('?abc', $result['title']); | 348 | $this->assertEquals('', $result->getTitle()); |
345 | $this->assertEquals('', $result['description']); | 349 | $this->assertEquals('', $result->getDescription()); |
346 | $this->assertEquals('', $result['tags']); | 350 | $this->assertEquals('', $result->getTagsString()); |
347 | $this->assertEquals(false, $result['private']); | 351 | $this->assertEquals(false, $result->isPrivate()); |
348 | $this->assertEquals($created, $result['created']); | 352 | $this->assertEquals($created, $result->getCreated()); |
349 | $this->assertTrue(new \DateTime('5 seconds ago') < $result['updated']); | ||
350 | } | 353 | } |
351 | } | 354 | } |