1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types = 1); |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Saito - The Threaded Web Forum |
7
|
|
|
* |
8
|
|
|
* @copyright Copyright (c) the Saito Project Developers |
9
|
|
|
* @link https://github.com/Schlaefer/Saito |
10
|
|
|
* @license http://opensource.org/licenses/MIT |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace ImageUploader\Test\TestCase\Controller; |
14
|
|
|
|
15
|
|
|
use Api\Error\Exception\GenericApiException; |
16
|
|
|
use Cake\Cache\Cache; |
17
|
|
|
use Cake\Core\Configure; |
18
|
|
|
use Cake\Core\Plugin; |
19
|
|
|
use Cake\Filesystem\File; |
20
|
|
|
use Cake\Http\Exception\UnauthorizedException; |
21
|
|
|
use Cake\ORM\TableRegistry; |
22
|
|
|
use claviska\SimpleImage; |
23
|
|
|
use Saito\Exception\SaitoForbiddenException; |
24
|
|
|
use Saito\Test\IntegrationTestCase; |
25
|
|
|
|
26
|
|
|
class UploadsControllerTest extends IntegrationTestCase |
27
|
|
|
{ |
28
|
|
|
public $fixtures = [ |
29
|
|
|
'app.Category', |
30
|
|
|
'app.Entry', |
31
|
|
|
'app.Setting', |
32
|
|
|
'app.User', |
33
|
|
|
'app.UserBlock', |
34
|
|
|
'app.UserRead', |
35
|
|
|
'app.UserOnline', |
36
|
|
|
'plugin.ImageUploader.Uploads', |
37
|
|
|
]; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var File dummy file |
41
|
|
|
*/ |
42
|
|
|
private $file; |
43
|
|
|
|
44
|
|
|
public function setUp() |
45
|
|
|
{ |
46
|
|
|
parent::setUp(); |
47
|
|
|
|
48
|
|
|
$this->file = new File(TMP . 'my new-upload.png'); |
49
|
|
|
$this->mockMediaFile($this->file); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
public function tearDown() |
53
|
|
|
{ |
54
|
|
|
$this->file->delete(); |
55
|
|
|
unset($this->file); |
56
|
|
|
|
57
|
|
|
parent::tearDown(); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
public function testAddNotAuthorized() |
61
|
|
|
{ |
62
|
|
|
$this->expectException(UnauthorizedException::class); |
63
|
|
|
|
64
|
|
|
$this->post('api/v2/uploads', []); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* png is successfully uploaded and converted to jpeg |
69
|
|
|
*/ |
70
|
|
|
public function testAddSuccess() |
71
|
|
|
{ |
72
|
|
|
$this->loginJwt(1); |
73
|
|
|
|
74
|
|
|
$this->upload($this->file); |
75
|
|
|
$response = json_decode((string)$this->_response->getBody(), true); |
76
|
|
|
|
77
|
|
|
$this->assertResponseCode(200); |
78
|
|
|
|
79
|
|
|
$this->assertWithinRange( |
80
|
|
|
time(), |
81
|
|
|
strtotime($response['data']['attributes']['created']), |
82
|
|
|
3 |
83
|
|
|
); |
84
|
|
|
unset($response['data']['attributes']['created']); |
85
|
|
|
|
86
|
|
|
$this->assertGreaterThan(0, $response['data']['attributes']['size']); |
87
|
|
|
unset($response['data']['attributes']['size']); |
88
|
|
|
|
89
|
|
|
$expected = [ |
90
|
|
|
'data' => [ |
91
|
|
|
'id' => 3, |
92
|
|
|
'type' => 'uploads', |
93
|
|
|
'attributes' => [ |
94
|
|
|
'id' => 3, |
95
|
|
|
'mime' => 'image/jpeg', |
96
|
|
|
'name' => '1_ebd536d37aff03f2b570329b20ece832.jpg', |
97
|
|
|
'thumbnail_url' => '/api/v2/uploads/thumb/3?h=e1fddb2ea8f448fac14ec06b88d4ce94', |
98
|
|
|
'title' => 'my new-upload.png', |
99
|
|
|
'url' => '/useruploads/1_ebd536d37aff03f2b570329b20ece832.jpg', |
100
|
|
|
], |
101
|
|
|
], |
102
|
|
|
]; |
103
|
|
|
$this->assertEquals($expected, $response); |
104
|
|
|
|
105
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
106
|
|
|
$upload = $Uploads->get(3); |
107
|
|
|
|
108
|
|
|
$this->assertSame('1_ebd536d37aff03f2b570329b20ece832.jpg', $upload->get('name')); |
109
|
|
|
$this->assertSame('image/jpeg', $upload->get('type')); |
110
|
|
|
$this->assertTrue($upload->get('file')->exists()); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
public function testAddSvg() |
114
|
|
|
{ |
115
|
|
|
$this->loginJwt(1); |
116
|
|
|
|
117
|
|
|
$this->file = new File(TMP . 'tmp_svg.svg'); |
118
|
|
|
$this->file->write('<?xml version="1.0" encoding="UTF-8" ?> |
119
|
|
|
<svg width="9" height="9" style="background:red;"></svg>'); |
120
|
|
|
$this->upload($this->file); |
121
|
|
|
|
122
|
|
|
$response = json_decode((string)$this->_response->getBody(), true); |
123
|
|
|
|
124
|
|
|
$this->assertResponseCode(200); |
125
|
|
|
|
126
|
|
|
$this->assertWithinRange( |
127
|
|
|
time(), |
128
|
|
|
strtotime($response['data']['attributes']['created']), |
129
|
|
|
3 |
130
|
|
|
); |
131
|
|
|
unset($response['data']['attributes']['created']); |
132
|
|
|
|
133
|
|
|
$expected = [ |
134
|
|
|
'data' => [ |
135
|
|
|
'id' => 3, |
136
|
|
|
'type' => 'uploads', |
137
|
|
|
'attributes' => [ |
138
|
|
|
'id' => 3, |
139
|
|
|
'mime' => 'image/svg+xml', |
140
|
|
|
'name' => '1_853fe7aa4ef213b0c11f4b739cf444a8.svg', |
141
|
|
|
'size' => 108, |
142
|
|
|
'thumbnail_url' => '/api/v2/uploads/thumb/3?h=1d57b148ad44d4caf90fa1cd98729678', |
143
|
|
|
'title' => 'tmp_svg.svg', |
144
|
|
|
'url' => '/useruploads/1_853fe7aa4ef213b0c11f4b739cf444a8.svg', |
145
|
|
|
], |
146
|
|
|
], |
147
|
|
|
]; |
148
|
|
|
$this->assertEquals($expected, $response); |
149
|
|
|
|
150
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
151
|
|
|
$upload = $Uploads->get(3); |
152
|
|
|
|
153
|
|
|
$this->assertSame('1_853fe7aa4ef213b0c11f4b739cf444a8.svg', $upload->get('name')); |
154
|
|
|
$this->assertSame('image/svg+xml', $upload->get('type')); |
155
|
|
|
$this->assertTrue($upload->get('file')->exists()); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function testRemoveExifData() |
159
|
|
|
{ |
160
|
|
|
$this->loginJwt(1); |
161
|
|
|
unset($this->file); |
162
|
|
|
$this->file = new File(TMP . 'tmp_exif.jpg'); |
163
|
|
|
|
164
|
|
|
$fixture = new File($path = Plugin::path('ImageUploader') . 'tests/Fixture/exif-with-location.jpg'); |
165
|
|
|
$fixture->copy($this->file->path); |
166
|
|
|
|
167
|
|
|
$readExif = function (File $file) { |
168
|
|
|
//@codingStandardsIgnoreStart |
169
|
|
|
return @exif_read_data($file->path); |
170
|
|
|
//@codingStandardsIgnoreEnd |
171
|
|
|
}; |
172
|
|
|
$exif = $readExif($this->file); |
173
|
|
|
$this->assertNotEmpty($exif['SectionsFound']); |
174
|
|
|
$this->assertContains('EXIF', $exif['SectionsFound']); |
175
|
|
|
$this->assertContains('IFD0', $exif['SectionsFound']); |
176
|
|
|
|
177
|
|
|
$this->upload($this->file); |
178
|
|
|
|
179
|
|
|
$response = json_decode((string)$this->_response->getBody(), true); |
|
|
|
|
180
|
|
|
|
181
|
|
|
$this->assertResponseCode(200); |
182
|
|
|
|
183
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
184
|
|
|
$upload = $Uploads->find('all')->last(); |
185
|
|
|
|
186
|
|
|
$exif = $readExif($upload->get('file')); |
187
|
|
|
$this->assertNotContains('EXIF', $exif['SectionsFound']); |
188
|
|
|
$this->assertNotContains('IFD0', $exif['SectionsFound']); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
View Code Duplication |
public function testAddFailureMaxUploadsPerUser() |
|
|
|
|
192
|
|
|
{ |
193
|
|
|
Configure::read('Saito.Settings.uploader')->setMaxNumberOfUploadsPerUser(1); |
194
|
|
|
$this->loginJwt(1); |
195
|
|
|
|
196
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
197
|
|
|
$count = $Uploads->find()->count(); |
198
|
|
|
|
199
|
|
|
$this->expectException(GenericApiException::class); |
200
|
|
|
$this->expectExceptionMessage('Error: Reached the maximal number of 1 uploads.'); |
201
|
|
|
|
202
|
|
|
$this->upload($this->file); |
203
|
|
|
|
204
|
|
|
$this->assertEquals($count, $Uploads->find()->count()); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
View Code Duplication |
public function testAddFailureMaxDocumentSize() |
|
|
|
|
208
|
|
|
{ |
209
|
|
|
Configure::read('Saito.Settings.uploader') |
210
|
|
|
->setMaxNumberOfUploadsPerUser(10) |
211
|
|
|
->addType('image/png', 10); |
212
|
|
|
|
213
|
|
|
$this->loginJwt(1); |
214
|
|
|
|
215
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
216
|
|
|
$count = $Uploads->find()->count(); |
217
|
|
|
|
218
|
|
|
$this->expectException(GenericApiException::class); |
219
|
|
|
$this->expectExceptionMessage('Error: File size exceeds allowed limit of 10 Bytes.'); |
220
|
|
|
|
221
|
|
|
$this->upload($this->file); |
222
|
|
|
|
223
|
|
|
$this->assertEquals($count, $Uploads->find()->count()); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
public function testIndexNoAuthorization() |
227
|
|
|
{ |
228
|
|
|
$this->expectException(UnauthorizedException::class); |
229
|
|
|
|
230
|
|
|
$this->get('api/v2/uploads'); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
public function testIndexSuccess() |
234
|
|
|
{ |
235
|
|
|
$this->loginJwt(3); |
236
|
|
|
|
237
|
|
|
$this->get('api/v2/uploads'); |
238
|
|
|
|
239
|
|
|
$response = json_decode((string)$this->_response->getBody(), true); |
240
|
|
|
|
241
|
|
|
$this->assertResponseCode(200); |
242
|
|
|
|
243
|
|
|
$this->assertEquals( |
244
|
|
|
1526404380, |
245
|
|
|
strtotime($response['data'][0]['attributes']['created']) |
246
|
|
|
); |
247
|
|
|
unset($response['data'][0]['attributes']['created']); |
248
|
|
|
|
249
|
|
|
$expected = [ |
250
|
|
|
'data' => [ |
251
|
|
|
[ |
252
|
|
|
'id' => 2, |
253
|
|
|
'type' => 'uploads', |
254
|
|
|
'attributes' => [ |
255
|
|
|
'id' => 2, |
256
|
|
|
'mime' => 'image/jpeg', |
257
|
|
|
'name' => '3-another-upload.jpg', |
258
|
|
|
'size' => 50000, |
259
|
|
|
'thumbnail_url' => '/api/v2/uploads/thumb/2?h=be7ef71551c4245f82223d0c8e652eee', |
260
|
|
|
'title' => '3-another-upload.jpg', |
261
|
|
|
'url' => '/useruploads/3-another-upload.jpg', |
262
|
|
|
], |
263
|
|
|
], |
264
|
|
|
], |
265
|
|
|
]; |
266
|
|
|
$this->assertEquals($expected, $response); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
public function testDeleteNoAuthorization() |
270
|
|
|
{ |
271
|
|
|
$this->expectException(UnauthorizedException::class); |
272
|
|
|
|
273
|
|
|
$this->delete('api/v2/uploads/1'); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
public function testDeleteSuccess() |
277
|
|
|
{ |
278
|
|
|
$this->loginJwt(1); |
279
|
|
|
$Uploads = TableRegistry::get('ImageUploader.Uploads'); |
|
|
|
|
280
|
|
|
$upload = $Uploads->get(1); |
281
|
|
|
$this->assertNotEmpty($Uploads->get(1)); |
282
|
|
|
$this->mockMediaFile($upload->get('file')); |
283
|
|
|
|
284
|
|
|
$this->delete('api/v2/uploads/1'); |
285
|
|
|
|
286
|
|
|
$response = json_decode((string)$this->_response->getBody(), true); |
|
|
|
|
287
|
|
|
|
288
|
|
|
$this->assertResponseCode(204); |
289
|
|
|
|
290
|
|
|
$this->assertFalse($Uploads->exists(1)); |
|
|
|
|
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
public function testDeleteFailureUploadBelongsToDifferentUser() |
294
|
|
|
{ |
295
|
|
|
$this->loginJwt(3); |
296
|
|
|
|
297
|
|
|
$this->expectException(SaitoForbiddenException::class); |
298
|
|
|
|
299
|
|
|
$this->delete('api/v2/uploads/1'); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Sends a file to upload api |
304
|
|
|
* |
305
|
|
|
* @param File $file The file to send |
306
|
|
|
*/ |
307
|
|
|
private function upload(File $file) |
308
|
|
|
{ |
309
|
|
|
$data = [ |
310
|
|
|
'upload' => [ |
311
|
|
|
0 => [ |
312
|
|
|
'file' => [ |
313
|
|
|
'tmp_name' => $file->path, |
314
|
|
|
'name' => $file->name() . '.' . $this->file->ext(), |
315
|
|
|
'size' => $file->size(), |
316
|
|
|
'type' => $file->mime(), |
317
|
|
|
] |
318
|
|
|
] |
319
|
|
|
] |
320
|
|
|
]; |
321
|
|
|
$this->post('api/v2/uploads.json', $data); |
322
|
|
|
} |
323
|
|
|
} |
324
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.