Completed
Push — master ( a9e3f6...bd00b7 )
by John
28:00 queued 14s
created
apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php 1 patch
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -28,142 +28,142 @@
 block discarded – undo
28 28
 use Test\TestCase;
29 29
 
30 30
 class ViewOnlyPluginTest extends TestCase {
31
-	private Tree&MockObject $tree;
32
-	private RequestInterface&MockObject $request;
33
-	private Folder&MockObject $userFolder;
34
-	private ViewOnlyPlugin $plugin;
35
-
36
-	public function setUp(): void {
37
-		parent::setUp();
38
-
39
-		$this->userFolder = $this->createMock(Folder::class);
40
-		$this->request = $this->createMock(RequestInterface::class);
41
-		$this->tree = $this->createMock(Tree::class);
42
-		$server = $this->createMock(Server::class);
43
-
44
-		$this->plugin = new ViewOnlyPlugin(
45
-			$this->userFolder,
46
-		);
47
-		$server->tree = $this->tree;
48
-
49
-		$this->plugin->initialize($server);
50
-	}
51
-
52
-	public function testCanGetNonDav(): void {
53
-		$this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
54
-		$this->tree->method('getNodeForPath')->willReturn(null);
55
-
56
-		$this->assertTrue($this->plugin->checkViewOnly($this->request));
57
-	}
58
-
59
-	public function testCanGetNonShared(): void {
60
-		$this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
61
-		$davNode = $this->createMock(DavFile::class);
62
-		$this->tree->method('getNodeForPath')->willReturn($davNode);
63
-
64
-		$file = $this->createMock(File::class);
65
-		$davNode->method('getNode')->willReturn($file);
66
-
67
-		$storage = $this->createMock(IStorage::class);
68
-		$file->method('getStorage')->willReturn($storage);
69
-		$storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false);
70
-
71
-		$this->assertTrue($this->plugin->checkViewOnly($this->request));
72
-	}
73
-
74
-	public static function providesDataForCanGet(): array {
75
-		return [
76
-			// has attribute permissions-download enabled - can get file
77
-			[false, true, true, true],
78
-			// has no attribute permissions-download - can get file
79
-			[false, null, true, true],
80
-			// has attribute permissions-download enabled - can get file version
81
-			[true, true, true, true],
82
-			// has no attribute permissions-download - can get file version
83
-			[true, null, true, true],
84
-			// has attribute permissions-download disabled - cannot get the file
85
-			[false, false, false, false],
86
-			// has attribute permissions-download disabled - cannot get the file version
87
-			[true, false, false, false],
88
-
89
-			// Has global allowViewWithoutDownload option enabled
90
-			// has attribute permissions-download disabled - can get file
91
-			[false, false, false, true],
92
-			// has attribute permissions-download disabled - can get file version
93
-			[true, false, false, true],
94
-		];
95
-	}
96
-
97
-	/**
98
-	 * @dataProvider providesDataForCanGet
99
-	 */
100
-	public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
101
-		$nodeInfo = $this->createMock(File::class);
102
-		if ($isVersion) {
103
-			$davPath = 'versions/alice/versions/117/123456';
104
-			$version = $this->createMock(IVersion::class);
105
-			$version->expects($this->once())
106
-				->method('getSourceFile')
107
-				->willReturn($nodeInfo);
108
-			$davNode = $this->createMock(VersionFile::class);
109
-			$davNode->expects($this->once())
110
-				->method('getVersion')
111
-				->willReturn($version);
112
-
113
-			$currentUser = $this->createMock(IUser::class);
114
-			$currentUser->expects($this->once())
115
-				->method('getUID')
116
-				->willReturn('alice');
117
-			$nodeInfo->expects($this->once())
118
-				->method('getOwner')
119
-				->willReturn($currentUser);
120
-
121
-			$nodeInfo = $this->createMock(File::class);
122
-			$owner = $this->createMock(IUser::class);
123
-			$owner->expects($this->once())
124
-				->method('getUID')
125
-				->willReturn('bob');
126
-			$this->userFolder->expects($this->once())
127
-				->method('getById')
128
-				->willReturn([$nodeInfo]);
129
-			$this->userFolder->expects($this->once())
130
-				->method('getOwner')
131
-				->willReturn($owner);
132
-		} else {
133
-			$davPath = 'files/path/to/file.odt';
134
-			$davNode = $this->createMock(DavFile::class);
135
-			$davNode->method('getNode')->willReturn($nodeInfo);
136
-		}
137
-
138
-		$this->request->expects($this->once())->method('getPath')->willReturn($davPath);
139
-
140
-		$this->tree->expects($this->once())
141
-			->method('getNodeForPath')
142
-			->with($davPath)
143
-			->willReturn($davNode);
144
-
145
-		$storage = $this->createMock(SharedStorage::class);
146
-		$share = $this->createMock(IShare::class);
147
-		$nodeInfo->expects($this->once())
148
-			->method('getStorage')
149
-			->willReturn($storage);
150
-		$storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(true);
151
-		$storage->method('getShare')->willReturn($share);
152
-
153
-		$extAttr = $this->createMock(IAttributes::class);
154
-		$share->method('getAttributes')->willReturn($extAttr);
155
-		$extAttr->expects($this->once())
156
-			->method('getAttribute')
157
-			->with('permissions', 'download')
158
-			->willReturn($attrEnabled);
31
+    private Tree&MockObject $tree;
32
+    private RequestInterface&MockObject $request;
33
+    private Folder&MockObject $userFolder;
34
+    private ViewOnlyPlugin $plugin;
35
+
36
+    public function setUp(): void {
37
+        parent::setUp();
38
+
39
+        $this->userFolder = $this->createMock(Folder::class);
40
+        $this->request = $this->createMock(RequestInterface::class);
41
+        $this->tree = $this->createMock(Tree::class);
42
+        $server = $this->createMock(Server::class);
43
+
44
+        $this->plugin = new ViewOnlyPlugin(
45
+            $this->userFolder,
46
+        );
47
+        $server->tree = $this->tree;
48
+
49
+        $this->plugin->initialize($server);
50
+    }
51
+
52
+    public function testCanGetNonDav(): void {
53
+        $this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
54
+        $this->tree->method('getNodeForPath')->willReturn(null);
55
+
56
+        $this->assertTrue($this->plugin->checkViewOnly($this->request));
57
+    }
58
+
59
+    public function testCanGetNonShared(): void {
60
+        $this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
61
+        $davNode = $this->createMock(DavFile::class);
62
+        $this->tree->method('getNodeForPath')->willReturn($davNode);
63
+
64
+        $file = $this->createMock(File::class);
65
+        $davNode->method('getNode')->willReturn($file);
66
+
67
+        $storage = $this->createMock(IStorage::class);
68
+        $file->method('getStorage')->willReturn($storage);
69
+        $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false);
70
+
71
+        $this->assertTrue($this->plugin->checkViewOnly($this->request));
72
+    }
73
+
74
+    public static function providesDataForCanGet(): array {
75
+        return [
76
+            // has attribute permissions-download enabled - can get file
77
+            [false, true, true, true],
78
+            // has no attribute permissions-download - can get file
79
+            [false, null, true, true],
80
+            // has attribute permissions-download enabled - can get file version
81
+            [true, true, true, true],
82
+            // has no attribute permissions-download - can get file version
83
+            [true, null, true, true],
84
+            // has attribute permissions-download disabled - cannot get the file
85
+            [false, false, false, false],
86
+            // has attribute permissions-download disabled - cannot get the file version
87
+            [true, false, false, false],
88
+
89
+            // Has global allowViewWithoutDownload option enabled
90
+            // has attribute permissions-download disabled - can get file
91
+            [false, false, false, true],
92
+            // has attribute permissions-download disabled - can get file version
93
+            [true, false, false, true],
94
+        ];
95
+    }
96
+
97
+    /**
98
+     * @dataProvider providesDataForCanGet
99
+     */
100
+    public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
101
+        $nodeInfo = $this->createMock(File::class);
102
+        if ($isVersion) {
103
+            $davPath = 'versions/alice/versions/117/123456';
104
+            $version = $this->createMock(IVersion::class);
105
+            $version->expects($this->once())
106
+                ->method('getSourceFile')
107
+                ->willReturn($nodeInfo);
108
+            $davNode = $this->createMock(VersionFile::class);
109
+            $davNode->expects($this->once())
110
+                ->method('getVersion')
111
+                ->willReturn($version);
112
+
113
+            $currentUser = $this->createMock(IUser::class);
114
+            $currentUser->expects($this->once())
115
+                ->method('getUID')
116
+                ->willReturn('alice');
117
+            $nodeInfo->expects($this->once())
118
+                ->method('getOwner')
119
+                ->willReturn($currentUser);
120
+
121
+            $nodeInfo = $this->createMock(File::class);
122
+            $owner = $this->createMock(IUser::class);
123
+            $owner->expects($this->once())
124
+                ->method('getUID')
125
+                ->willReturn('bob');
126
+            $this->userFolder->expects($this->once())
127
+                ->method('getById')
128
+                ->willReturn([$nodeInfo]);
129
+            $this->userFolder->expects($this->once())
130
+                ->method('getOwner')
131
+                ->willReturn($owner);
132
+        } else {
133
+            $davPath = 'files/path/to/file.odt';
134
+            $davNode = $this->createMock(DavFile::class);
135
+            $davNode->method('getNode')->willReturn($nodeInfo);
136
+        }
137
+
138
+        $this->request->expects($this->once())->method('getPath')->willReturn($davPath);
139
+
140
+        $this->tree->expects($this->once())
141
+            ->method('getNodeForPath')
142
+            ->with($davPath)
143
+            ->willReturn($davNode);
144
+
145
+        $storage = $this->createMock(SharedStorage::class);
146
+        $share = $this->createMock(IShare::class);
147
+        $nodeInfo->expects($this->once())
148
+            ->method('getStorage')
149
+            ->willReturn($storage);
150
+        $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(true);
151
+        $storage->method('getShare')->willReturn($share);
152
+
153
+        $extAttr = $this->createMock(IAttributes::class);
154
+        $share->method('getAttributes')->willReturn($extAttr);
155
+        $extAttr->expects($this->once())
156
+            ->method('getAttribute')
157
+            ->with('permissions', 'download')
158
+            ->willReturn($attrEnabled);
159 159
 		
160
-		$share->expects($this->once())
161
-			->method('canSeeContent')
162
-			->willReturn($allowViewWithoutDownload);
163
-
164
-		if (!$expectCanDownloadFile) {
165
-			$this->expectException(Forbidden::class);
166
-		}
167
-		$this->plugin->checkViewOnly($this->request);
168
-	}
160
+        $share->expects($this->once())
161
+            ->method('canSeeContent')
162
+            ->willReturn($allowViewWithoutDownload);
163
+
164
+        if (!$expectCanDownloadFile) {
165
+            $this->expectException(Forbidden::class);
166
+        }
167
+        $this->plugin->checkViewOnly($this->request);
168
+    }
169 169
 }
Please login to merge, or discard this patch.
tests/Core/Controller/PreviewControllerTest.php 1 patch
Indentation   +339 added lines, -339 removed lines patch added patch discarded remove patch
@@ -24,343 +24,343 @@
 block discarded – undo
24 24
 
25 25
 class PreviewControllerTest extends \Test\TestCase {
26 26
 
27
-	private string $userId;
28
-	private PreviewController $controller;
29
-
30
-	private IRootFolder&MockObject $rootFolder;
31
-	private IPreview&MockObject $previewManager;
32
-	private IRequest&MockObject $request;
33
-
34
-	protected function setUp(): void {
35
-		parent::setUp();
36
-
37
-		$this->userId = 'user';
38
-		$this->rootFolder = $this->createMock(IRootFolder::class);
39
-		$this->previewManager = $this->createMock(IPreview::class);
40
-		$this->request = $this->createMock(IRequest::class);
41
-
42
-		$this->controller = new PreviewController(
43
-			'core',
44
-			$this->request,
45
-			$this->previewManager,
46
-			$this->rootFolder,
47
-			$this->userId,
48
-			$this->createMock(IMimeIconProvider::class)
49
-		);
50
-	}
51
-
52
-	public function testInvalidFile(): void {
53
-		$res = $this->controller->getPreview('');
54
-		$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
55
-
56
-		$this->assertEquals($expected, $res);
57
-	}
58
-
59
-	public function testInvalidWidth(): void {
60
-		$res = $this->controller->getPreview('file', 0);
61
-		$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
62
-
63
-		$this->assertEquals($expected, $res);
64
-	}
65
-
66
-	public function testInvalidHeight(): void {
67
-		$res = $this->controller->getPreview('file', 10, 0);
68
-		$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
69
-
70
-		$this->assertEquals($expected, $res);
71
-	}
72
-
73
-	public function testFileNotFound(): void {
74
-		$userFolder = $this->createMock(Folder::class);
75
-		$this->rootFolder->method('getUserFolder')
76
-			->with($this->equalTo($this->userId))
77
-			->willReturn($userFolder);
78
-
79
-		$userFolder->method('get')
80
-			->with($this->equalTo('file'))
81
-			->willThrowException(new NotFoundException());
82
-
83
-		$res = $this->controller->getPreview('file');
84
-		$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
85
-
86
-		$this->assertEquals($expected, $res);
87
-	}
88
-
89
-	public function testNotAFile(): void {
90
-		$userFolder = $this->createMock(Folder::class);
91
-		$this->rootFolder->method('getUserFolder')
92
-			->with($this->equalTo($this->userId))
93
-			->willReturn($userFolder);
94
-
95
-		$folder = $this->createMock(Folder::class);
96
-		$userFolder->method('get')
97
-			->with($this->equalTo('file'))
98
-			->willReturn($folder);
99
-
100
-		$res = $this->controller->getPreview('file');
101
-		$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
102
-
103
-		$this->assertEquals($expected, $res);
104
-	}
105
-
106
-	public function testNoPreviewAndNoIcon(): void {
107
-		$userFolder = $this->createMock(Folder::class);
108
-		$this->rootFolder->method('getUserFolder')
109
-			->with($this->equalTo($this->userId))
110
-			->willReturn($userFolder);
111
-
112
-		$file = $this->createMock(File::class);
113
-		$userFolder->method('get')
114
-			->with($this->equalTo('file'))
115
-			->willReturn($file);
116
-
117
-		$this->previewManager->method('isAvailable')
118
-			->with($this->equalTo($file))
119
-			->willReturn(false);
120
-
121
-		$res = $this->controller->getPreview('file', 10, 10, true, false);
122
-		$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
123
-
124
-		$this->assertEquals($expected, $res);
125
-	}
126
-
127
-	public function testNoPreview() {
128
-		$userFolder = $this->createMock(Folder::class);
129
-		$this->rootFolder->method('getUserFolder')
130
-			->with($this->equalTo($this->userId))
131
-			->willReturn($userFolder);
132
-
133
-		$file = $this->createMock(File::class);
134
-		$userFolder->method('get')
135
-			->with($this->equalTo('file'))
136
-			->willReturn($file);
137
-
138
-		$storage = $this->createMock(IStorage::class);
139
-		$file->method('getStorage')
140
-			->willReturn($storage);
141
-
142
-		$this->previewManager->method('isAvailable')
143
-			->with($this->equalTo($file))
144
-			->willReturn(true);
145
-
146
-		$file->method('isReadable')
147
-			->willReturn(true);
148
-
149
-		$this->previewManager->method('getPreview')
150
-			->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
151
-			->willThrowException(new NotFoundException());
152
-
153
-		$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
154
-		$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
155
-
156
-		$this->assertEquals($expected, $res);
157
-	}
158
-	public function testFileWithoutReadPermission() {
159
-		$userFolder = $this->createMock(Folder::class);
160
-		$this->rootFolder->method('getUserFolder')
161
-			->with($this->equalTo($this->userId))
162
-			->willReturn($userFolder);
163
-
164
-		$file = $this->createMock(File::class);
165
-		$userFolder->method('get')
166
-			->with($this->equalTo('file'))
167
-			->willReturn($file);
168
-
169
-		$this->previewManager->method('isAvailable')
170
-			->with($this->equalTo($file))
171
-			->willReturn(true);
172
-
173
-		$file->method('isReadable')
174
-			->willReturn(false);
175
-
176
-		$res = $this->controller->getPreview('file', 10, 10, true, true);
177
-		$expected = new DataResponse([], Http::STATUS_FORBIDDEN);
178
-
179
-		$this->assertEquals($expected, $res);
180
-	}
181
-
182
-	public function testFileWithoutDownloadPermission() {
183
-		$userFolder = $this->createMock(Folder::class);
184
-		$this->rootFolder->method('getUserFolder')
185
-			->with($this->equalTo($this->userId))
186
-			->willReturn($userFolder);
187
-
188
-		$file = $this->createMock(File::class);
189
-		$file->method('getId')->willReturn(123);
190
-		$userFolder->method('get')
191
-			->with($this->equalTo('file'))
192
-			->willReturn($file);
193
-
194
-		$this->previewManager->method('isAvailable')
195
-			->with($this->equalTo($file))
196
-			->willReturn(true);
197
-
198
-		$share = $this->createMock(IShare::class);
199
-		$share->method('canSeeContent')
200
-			->willReturn(false);
201
-
202
-		$storage = $this->createMock(ISharedStorage::class);
203
-		$storage->method('instanceOfStorage')
204
-			->with(ISharedStorage::class)
205
-			->willReturn(true);
206
-		$storage->method('getShare')
207
-			->willReturn($share);
208
-
209
-		$file->method('getStorage')
210
-			->willReturn($storage);
211
-		$file->method('isReadable')
212
-			->willReturn(true);
213
-
214
-		$this->request->method('getHeader')->willReturn('');
215
-
216
-		$res = $this->controller->getPreview('file', 10, 10, true, true);
217
-		$expected = new DataResponse([], Http::STATUS_FORBIDDEN);
218
-
219
-		$this->assertEquals($expected, $res);
220
-	}
221
-
222
-	public function testFileWithoutDownloadPermissionButHeader() {
223
-		$userFolder = $this->createMock(Folder::class);
224
-		$this->rootFolder->method('getUserFolder')
225
-			->with($this->equalTo($this->userId))
226
-			->willReturn($userFolder);
227
-
228
-		$file = $this->createMock(File::class);
229
-		$file->method('getId')->willReturn(123);
230
-		$userFolder->method('get')
231
-			->with($this->equalTo('file'))
232
-			->willReturn($file);
233
-
234
-		$this->previewManager->method('isAvailable')
235
-			->with($this->equalTo($file))
236
-			->willReturn(true);
237
-
238
-		$share = $this->createMock(IShare::class);
239
-		$share->method('canSeeContent')
240
-			->willReturn(false);
241
-
242
-		$storage = $this->createMock(ISharedStorage::class);
243
-		$storage->method('instanceOfStorage')
244
-			->with(ISharedStorage::class)
245
-			->willReturn(true);
246
-		$storage->method('getShare')
247
-			->willReturn($share);
248
-
249
-		$file->method('getStorage')
250
-			->willReturn($storage);
251
-		$file->method('isReadable')
252
-			->willReturn(true);
253
-
254
-		$this->request
255
-			->method('getHeader')
256
-			->with('x-nc-preview')
257
-			->willReturn('true');
258
-
259
-		$preview = $this->createMock(ISimpleFile::class);
260
-		$preview->method('getName')->willReturn('my name');
261
-		$preview->method('getMTime')->willReturn(42);
262
-		$this->previewManager->method('getPreview')
263
-			->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
264
-			->willReturn($preview);
265
-		$preview->method('getMimeType')
266
-			->willReturn('myMime');
267
-
268
-		$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
269
-
270
-		$this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
271
-		$this->assertEquals(Http::STATUS_OK, $res->getStatus());
272
-		$this->assertEquals($preview, $this->invokePrivate($res, 'file'));
273
-	}
274
-
275
-	public function testValidPreview(): void {
276
-		$userFolder = $this->createMock(Folder::class);
277
-		$this->rootFolder->method('getUserFolder')
278
-			->with($this->equalTo($this->userId))
279
-			->willReturn($userFolder);
280
-
281
-		$file = $this->createMock(File::class);
282
-		$file->method('getId')->willReturn(123);
283
-		$userFolder->method('get')
284
-			->with($this->equalTo('file'))
285
-			->willReturn($file);
286
-
287
-		$this->previewManager->method('isAvailable')
288
-			->with($this->equalTo($file))
289
-			->willReturn(true);
290
-
291
-		$file->method('isReadable')
292
-			->willReturn(true);
293
-
294
-		$storage = $this->createMock(IStorage::class);
295
-		$file->method('getStorage')
296
-			->willReturn($storage);
297
-
298
-		$preview = $this->createMock(ISimpleFile::class);
299
-		$preview->method('getName')->willReturn('my name');
300
-		$preview->method('getMTime')->willReturn(42);
301
-		$this->previewManager->method('getPreview')
302
-			->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
303
-			->willReturn($preview);
304
-		$preview->method('getMimeType')
305
-			->willReturn('myMime');
306
-
307
-		$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
308
-
309
-		$this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
310
-		$this->assertEquals(Http::STATUS_OK, $res->getStatus());
311
-		$this->assertEquals($preview, $this->invokePrivate($res, 'file'));
312
-	}
313
-
314
-	public function testValidPreviewOfShare() {
315
-		$userFolder = $this->createMock(Folder::class);
316
-		$this->rootFolder->method('getUserFolder')
317
-			->with($this->equalTo($this->userId))
318
-			->willReturn($userFolder);
319
-
320
-		$file = $this->createMock(File::class);
321
-		$file->method('getId')->willReturn(123);
322
-		$userFolder->method('get')
323
-			->with($this->equalTo('file'))
324
-			->willReturn($file);
325
-
326
-		$this->previewManager->method('isAvailable')
327
-			->with($this->equalTo($file))
328
-			->willReturn(true);
329
-
330
-		// No attributes set -> download permitted
331
-		$share = $this->createMock(IShare::class);
332
-		$share->method('canSeeContent')
333
-			->willReturn(true);
334
-
335
-		$storage = $this->createMock(ISharedStorage::class);
336
-		$storage->method('instanceOfStorage')
337
-			->with(ISharedStorage::class)
338
-			->willReturn(true);
339
-		$storage->method('getShare')
340
-			->willReturn($share);
341
-
342
-		$file->method('getStorage')
343
-			->willReturn($storage);
344
-		$file->method('isReadable')
345
-			->willReturn(true);
346
-
347
-		$this->request
348
-			->method('getHeader')
349
-			->willReturn('');
350
-
351
-		$preview = $this->createMock(ISimpleFile::class);
352
-		$preview->method('getName')->willReturn('my name');
353
-		$preview->method('getMTime')->willReturn(42);
354
-		$this->previewManager->method('getPreview')
355
-			->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
356
-			->willReturn($preview);
357
-		$preview->method('getMimeType')
358
-			->willReturn('myMime');
359
-
360
-		$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
361
-
362
-		$this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
363
-		$this->assertEquals(Http::STATUS_OK, $res->getStatus());
364
-		$this->assertEquals($preview, $this->invokePrivate($res, 'file'));
365
-	}
27
+    private string $userId;
28
+    private PreviewController $controller;
29
+
30
+    private IRootFolder&MockObject $rootFolder;
31
+    private IPreview&MockObject $previewManager;
32
+    private IRequest&MockObject $request;
33
+
34
+    protected function setUp(): void {
35
+        parent::setUp();
36
+
37
+        $this->userId = 'user';
38
+        $this->rootFolder = $this->createMock(IRootFolder::class);
39
+        $this->previewManager = $this->createMock(IPreview::class);
40
+        $this->request = $this->createMock(IRequest::class);
41
+
42
+        $this->controller = new PreviewController(
43
+            'core',
44
+            $this->request,
45
+            $this->previewManager,
46
+            $this->rootFolder,
47
+            $this->userId,
48
+            $this->createMock(IMimeIconProvider::class)
49
+        );
50
+    }
51
+
52
+    public function testInvalidFile(): void {
53
+        $res = $this->controller->getPreview('');
54
+        $expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
55
+
56
+        $this->assertEquals($expected, $res);
57
+    }
58
+
59
+    public function testInvalidWidth(): void {
60
+        $res = $this->controller->getPreview('file', 0);
61
+        $expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
62
+
63
+        $this->assertEquals($expected, $res);
64
+    }
65
+
66
+    public function testInvalidHeight(): void {
67
+        $res = $this->controller->getPreview('file', 10, 0);
68
+        $expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
69
+
70
+        $this->assertEquals($expected, $res);
71
+    }
72
+
73
+    public function testFileNotFound(): void {
74
+        $userFolder = $this->createMock(Folder::class);
75
+        $this->rootFolder->method('getUserFolder')
76
+            ->with($this->equalTo($this->userId))
77
+            ->willReturn($userFolder);
78
+
79
+        $userFolder->method('get')
80
+            ->with($this->equalTo('file'))
81
+            ->willThrowException(new NotFoundException());
82
+
83
+        $res = $this->controller->getPreview('file');
84
+        $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
85
+
86
+        $this->assertEquals($expected, $res);
87
+    }
88
+
89
+    public function testNotAFile(): void {
90
+        $userFolder = $this->createMock(Folder::class);
91
+        $this->rootFolder->method('getUserFolder')
92
+            ->with($this->equalTo($this->userId))
93
+            ->willReturn($userFolder);
94
+
95
+        $folder = $this->createMock(Folder::class);
96
+        $userFolder->method('get')
97
+            ->with($this->equalTo('file'))
98
+            ->willReturn($folder);
99
+
100
+        $res = $this->controller->getPreview('file');
101
+        $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
102
+
103
+        $this->assertEquals($expected, $res);
104
+    }
105
+
106
+    public function testNoPreviewAndNoIcon(): void {
107
+        $userFolder = $this->createMock(Folder::class);
108
+        $this->rootFolder->method('getUserFolder')
109
+            ->with($this->equalTo($this->userId))
110
+            ->willReturn($userFolder);
111
+
112
+        $file = $this->createMock(File::class);
113
+        $userFolder->method('get')
114
+            ->with($this->equalTo('file'))
115
+            ->willReturn($file);
116
+
117
+        $this->previewManager->method('isAvailable')
118
+            ->with($this->equalTo($file))
119
+            ->willReturn(false);
120
+
121
+        $res = $this->controller->getPreview('file', 10, 10, true, false);
122
+        $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
123
+
124
+        $this->assertEquals($expected, $res);
125
+    }
126
+
127
+    public function testNoPreview() {
128
+        $userFolder = $this->createMock(Folder::class);
129
+        $this->rootFolder->method('getUserFolder')
130
+            ->with($this->equalTo($this->userId))
131
+            ->willReturn($userFolder);
132
+
133
+        $file = $this->createMock(File::class);
134
+        $userFolder->method('get')
135
+            ->with($this->equalTo('file'))
136
+            ->willReturn($file);
137
+
138
+        $storage = $this->createMock(IStorage::class);
139
+        $file->method('getStorage')
140
+            ->willReturn($storage);
141
+
142
+        $this->previewManager->method('isAvailable')
143
+            ->with($this->equalTo($file))
144
+            ->willReturn(true);
145
+
146
+        $file->method('isReadable')
147
+            ->willReturn(true);
148
+
149
+        $this->previewManager->method('getPreview')
150
+            ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
151
+            ->willThrowException(new NotFoundException());
152
+
153
+        $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
154
+        $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
155
+
156
+        $this->assertEquals($expected, $res);
157
+    }
158
+    public function testFileWithoutReadPermission() {
159
+        $userFolder = $this->createMock(Folder::class);
160
+        $this->rootFolder->method('getUserFolder')
161
+            ->with($this->equalTo($this->userId))
162
+            ->willReturn($userFolder);
163
+
164
+        $file = $this->createMock(File::class);
165
+        $userFolder->method('get')
166
+            ->with($this->equalTo('file'))
167
+            ->willReturn($file);
168
+
169
+        $this->previewManager->method('isAvailable')
170
+            ->with($this->equalTo($file))
171
+            ->willReturn(true);
172
+
173
+        $file->method('isReadable')
174
+            ->willReturn(false);
175
+
176
+        $res = $this->controller->getPreview('file', 10, 10, true, true);
177
+        $expected = new DataResponse([], Http::STATUS_FORBIDDEN);
178
+
179
+        $this->assertEquals($expected, $res);
180
+    }
181
+
182
+    public function testFileWithoutDownloadPermission() {
183
+        $userFolder = $this->createMock(Folder::class);
184
+        $this->rootFolder->method('getUserFolder')
185
+            ->with($this->equalTo($this->userId))
186
+            ->willReturn($userFolder);
187
+
188
+        $file = $this->createMock(File::class);
189
+        $file->method('getId')->willReturn(123);
190
+        $userFolder->method('get')
191
+            ->with($this->equalTo('file'))
192
+            ->willReturn($file);
193
+
194
+        $this->previewManager->method('isAvailable')
195
+            ->with($this->equalTo($file))
196
+            ->willReturn(true);
197
+
198
+        $share = $this->createMock(IShare::class);
199
+        $share->method('canSeeContent')
200
+            ->willReturn(false);
201
+
202
+        $storage = $this->createMock(ISharedStorage::class);
203
+        $storage->method('instanceOfStorage')
204
+            ->with(ISharedStorage::class)
205
+            ->willReturn(true);
206
+        $storage->method('getShare')
207
+            ->willReturn($share);
208
+
209
+        $file->method('getStorage')
210
+            ->willReturn($storage);
211
+        $file->method('isReadable')
212
+            ->willReturn(true);
213
+
214
+        $this->request->method('getHeader')->willReturn('');
215
+
216
+        $res = $this->controller->getPreview('file', 10, 10, true, true);
217
+        $expected = new DataResponse([], Http::STATUS_FORBIDDEN);
218
+
219
+        $this->assertEquals($expected, $res);
220
+    }
221
+
222
+    public function testFileWithoutDownloadPermissionButHeader() {
223
+        $userFolder = $this->createMock(Folder::class);
224
+        $this->rootFolder->method('getUserFolder')
225
+            ->with($this->equalTo($this->userId))
226
+            ->willReturn($userFolder);
227
+
228
+        $file = $this->createMock(File::class);
229
+        $file->method('getId')->willReturn(123);
230
+        $userFolder->method('get')
231
+            ->with($this->equalTo('file'))
232
+            ->willReturn($file);
233
+
234
+        $this->previewManager->method('isAvailable')
235
+            ->with($this->equalTo($file))
236
+            ->willReturn(true);
237
+
238
+        $share = $this->createMock(IShare::class);
239
+        $share->method('canSeeContent')
240
+            ->willReturn(false);
241
+
242
+        $storage = $this->createMock(ISharedStorage::class);
243
+        $storage->method('instanceOfStorage')
244
+            ->with(ISharedStorage::class)
245
+            ->willReturn(true);
246
+        $storage->method('getShare')
247
+            ->willReturn($share);
248
+
249
+        $file->method('getStorage')
250
+            ->willReturn($storage);
251
+        $file->method('isReadable')
252
+            ->willReturn(true);
253
+
254
+        $this->request
255
+            ->method('getHeader')
256
+            ->with('x-nc-preview')
257
+            ->willReturn('true');
258
+
259
+        $preview = $this->createMock(ISimpleFile::class);
260
+        $preview->method('getName')->willReturn('my name');
261
+        $preview->method('getMTime')->willReturn(42);
262
+        $this->previewManager->method('getPreview')
263
+            ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
264
+            ->willReturn($preview);
265
+        $preview->method('getMimeType')
266
+            ->willReturn('myMime');
267
+
268
+        $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
269
+
270
+        $this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
271
+        $this->assertEquals(Http::STATUS_OK, $res->getStatus());
272
+        $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
273
+    }
274
+
275
+    public function testValidPreview(): void {
276
+        $userFolder = $this->createMock(Folder::class);
277
+        $this->rootFolder->method('getUserFolder')
278
+            ->with($this->equalTo($this->userId))
279
+            ->willReturn($userFolder);
280
+
281
+        $file = $this->createMock(File::class);
282
+        $file->method('getId')->willReturn(123);
283
+        $userFolder->method('get')
284
+            ->with($this->equalTo('file'))
285
+            ->willReturn($file);
286
+
287
+        $this->previewManager->method('isAvailable')
288
+            ->with($this->equalTo($file))
289
+            ->willReturn(true);
290
+
291
+        $file->method('isReadable')
292
+            ->willReturn(true);
293
+
294
+        $storage = $this->createMock(IStorage::class);
295
+        $file->method('getStorage')
296
+            ->willReturn($storage);
297
+
298
+        $preview = $this->createMock(ISimpleFile::class);
299
+        $preview->method('getName')->willReturn('my name');
300
+        $preview->method('getMTime')->willReturn(42);
301
+        $this->previewManager->method('getPreview')
302
+            ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
303
+            ->willReturn($preview);
304
+        $preview->method('getMimeType')
305
+            ->willReturn('myMime');
306
+
307
+        $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
308
+
309
+        $this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
310
+        $this->assertEquals(Http::STATUS_OK, $res->getStatus());
311
+        $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
312
+    }
313
+
314
+    public function testValidPreviewOfShare() {
315
+        $userFolder = $this->createMock(Folder::class);
316
+        $this->rootFolder->method('getUserFolder')
317
+            ->with($this->equalTo($this->userId))
318
+            ->willReturn($userFolder);
319
+
320
+        $file = $this->createMock(File::class);
321
+        $file->method('getId')->willReturn(123);
322
+        $userFolder->method('get')
323
+            ->with($this->equalTo('file'))
324
+            ->willReturn($file);
325
+
326
+        $this->previewManager->method('isAvailable')
327
+            ->with($this->equalTo($file))
328
+            ->willReturn(true);
329
+
330
+        // No attributes set -> download permitted
331
+        $share = $this->createMock(IShare::class);
332
+        $share->method('canSeeContent')
333
+            ->willReturn(true);
334
+
335
+        $storage = $this->createMock(ISharedStorage::class);
336
+        $storage->method('instanceOfStorage')
337
+            ->with(ISharedStorage::class)
338
+            ->willReturn(true);
339
+        $storage->method('getShare')
340
+            ->willReturn($share);
341
+
342
+        $file->method('getStorage')
343
+            ->willReturn($storage);
344
+        $file->method('isReadable')
345
+            ->willReturn(true);
346
+
347
+        $this->request
348
+            ->method('getHeader')
349
+            ->willReturn('');
350
+
351
+        $preview = $this->createMock(ISimpleFile::class);
352
+        $preview->method('getName')->willReturn('my name');
353
+        $preview->method('getMTime')->willReturn(42);
354
+        $this->previewManager->method('getPreview')
355
+            ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
356
+            ->willReturn($preview);
357
+        $preview->method('getMimeType')
358
+            ->willReturn('myMime');
359
+
360
+        $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
361
+
362
+        $this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
363
+        $this->assertEquals(Http::STATUS_OK, $res->getStatus());
364
+        $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
365
+    }
366 366
 }
Please login to merge, or discard this patch.
build/integration/features/bootstrap/SharingContext.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -13,24 +13,24 @@
 block discarded – undo
13 13
  * Features context.
14 14
  */
15 15
 class SharingContext implements Context, SnippetAcceptingContext {
16
-	use WebDav;
17
-	use Trashbin;
18
-	use AppConfiguration;
19
-	use CommandLine;
20
-	use Activity;
16
+    use WebDav;
17
+    use Trashbin;
18
+    use AppConfiguration;
19
+    use CommandLine;
20
+    use Activity;
21 21
 
22
-	protected function resetAppConfigs() {
23
-		$this->deleteServerConfig('core', 'shareapi_default_permissions');
24
-		$this->deleteServerConfig('core', 'shareapi_default_internal_expire_date');
25
-		$this->deleteServerConfig('core', 'shareapi_internal_expire_after_n_days');
26
-		$this->deleteServerConfig('core', 'internal_defaultExpDays');
27
-		$this->deleteServerConfig('core', 'shareapi_enforce_links_password');
28
-		$this->deleteServerConfig('core', 'shareapi_default_expire_date');
29
-		$this->deleteServerConfig('core', 'shareapi_expire_after_n_days');
30
-		$this->deleteServerConfig('core', 'link_defaultExpDays');
31
-		$this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled');
32
-		$this->deleteServerConfig('core', 'shareapi_allow_view_without_download');
22
+    protected function resetAppConfigs() {
23
+        $this->deleteServerConfig('core', 'shareapi_default_permissions');
24
+        $this->deleteServerConfig('core', 'shareapi_default_internal_expire_date');
25
+        $this->deleteServerConfig('core', 'shareapi_internal_expire_after_n_days');
26
+        $this->deleteServerConfig('core', 'internal_defaultExpDays');
27
+        $this->deleteServerConfig('core', 'shareapi_enforce_links_password');
28
+        $this->deleteServerConfig('core', 'shareapi_default_expire_date');
29
+        $this->deleteServerConfig('core', 'shareapi_expire_after_n_days');
30
+        $this->deleteServerConfig('core', 'link_defaultExpDays');
31
+        $this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled');
32
+        $this->deleteServerConfig('core', 'shareapi_allow_view_without_download');
33 33
 
34
-		$this->runOcc(['config:system:delete', 'share_folder']);
35
-	}
34
+        $this->runOcc(['config:system:delete', 'share_folder']);
35
+    }
36 36
 }
Please login to merge, or discard this patch.
core/Controller/PreviewController.php 1 patch
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -29,178 +29,178 @@
 block discarded – undo
29 29
 use OCP\Preview\IMimeIconProvider;
30 30
 
31 31
 class PreviewController extends Controller {
32
-	public function __construct(
33
-		string $appName,
34
-		IRequest $request,
35
-		private IPreview $preview,
36
-		private IRootFolder $root,
37
-		private ?string $userId,
38
-		private IMimeIconProvider $mimeIconProvider,
39
-	) {
40
-		parent::__construct($appName, $request);
41
-	}
42
-
43
-	/**
44
-	 * Get a preview by file path
45
-	 *
46
-	 * @param string $file Path of the file
47
-	 * @param int $x Width of the preview. A width of -1 will use the original image width.
48
-	 * @param int $y Height of the preview. A height of -1 will use the original image height.
49
-	 * @param bool $a Preserve the aspect ratio
50
-	 * @param bool $forceIcon Force returning an icon
51
-	 * @param 'fill'|'cover' $mode How to crop the image
52
-	 * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
53
-	 * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
54
-	 *
55
-	 * 200: Preview returned
56
-	 * 303: Redirect to the mime icon url if mimeFallback is true
57
-	 * 400: Getting preview is not possible
58
-	 * 403: Getting preview is not allowed
59
-	 * 404: Preview not found
60
-	 */
61
-	#[NoAdminRequired]
62
-	#[NoCSRFRequired]
63
-	#[FrontpageRoute(verb: 'GET', url: '/core/preview.png')]
64
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
65
-	public function getPreview(
66
-		string $file = '',
67
-		int $x = 32,
68
-		int $y = 32,
69
-		bool $a = false,
70
-		bool $forceIcon = true,
71
-		string $mode = 'fill',
72
-		bool $mimeFallback = false): Response {
73
-		if ($file === '' || $x === 0 || $y === 0) {
74
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
75
-		}
76
-
77
-		try {
78
-			$userFolder = $this->root->getUserFolder($this->userId);
79
-			$node = $userFolder->get($file);
80
-		} catch (NotFoundException $e) {
81
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
82
-		}
83
-
84
-		return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback);
85
-	}
86
-
87
-	/**
88
-	 * Get a preview by file ID
89
-	 *
90
-	 * @param int $fileId ID of the file
91
-	 * @param int $x Width of the preview. A width of -1 will use the original image width.
92
-	 * @param int $y Height of the preview. A height of -1 will use the original image height.
93
-	 * @param bool $a Preserve the aspect ratio
94
-	 * @param bool $forceIcon Force returning an icon
95
-	 * @param 'fill'|'cover' $mode How to crop the image
96
-	 * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
97
-	 * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
98
-	 *
99
-	 * 200: Preview returned
100
-	 * 303: Redirect to the mime icon url if mimeFallback is true
101
-	 * 400: Getting preview is not possible
102
-	 * 403: Getting preview is not allowed
103
-	 * 404: Preview not found
104
-	 */
105
-	#[NoAdminRequired]
106
-	#[NoCSRFRequired]
107
-	#[FrontpageRoute(verb: 'GET', url: '/core/preview')]
108
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
109
-	public function getPreviewByFileId(
110
-		int $fileId = -1,
111
-		int $x = 32,
112
-		int $y = 32,
113
-		bool $a = false,
114
-		bool $forceIcon = true,
115
-		string $mode = 'fill',
116
-		bool $mimeFallback = false) {
117
-		if ($fileId === -1 || $x === 0 || $y === 0) {
118
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
119
-		}
120
-
121
-		$userFolder = $this->root->getUserFolder($this->userId);
122
-		$node = $userFolder->getFirstNodeById($fileId);
123
-
124
-		if (!$node) {
125
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
126
-		}
127
-
128
-		return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback);
129
-	}
130
-
131
-	/**
132
-	 * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
133
-	 */
134
-	private function fetchPreview(
135
-		Node $node,
136
-		int $x,
137
-		int $y,
138
-		bool $a,
139
-		bool $forceIcon,
140
-		string $mode,
141
-		bool $mimeFallback = false) : Response {
142
-		if (!($node instanceof File) || (!$forceIcon && !$this->preview->isAvailable($node))) {
143
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
144
-		}
145
-		if (!$node->isReadable()) {
146
-			return new DataResponse([], Http::STATUS_FORBIDDEN);
147
-		}
148
-
149
-		if ($node->getId() <= 0) {
150
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
151
-		}
152
-
153
-		// Is this header is set it means our UI is doing a preview for no-download shares
154
-		// we check a header so we at least prevent people from using the link directly (obfuscation)
155
-		$isNextcloudPreview = $this->request->getHeader('x-nc-preview') === 'true';
156
-		$storage = $node->getStorage();
157
-		if ($isNextcloudPreview === false && $storage->instanceOfStorage(ISharedStorage::class)) {
158
-			/** @var ISharedStorage $storage */
159
-			$share = $storage->getShare();
160
-			if (!$share->canSeeContent()) {
161
-				return new DataResponse([], Http::STATUS_FORBIDDEN);
162
-			}
163
-		}
164
-
165
-		try {
166
-			$f = $this->preview->getPreview($node, $x, $y, !$a, $mode);
167
-			$response = new FileDisplayResponse($f, Http::STATUS_OK, [
168
-				'Content-Type' => $f->getMimeType(),
169
-			]);
170
-			$response->cacheFor(3600 * 24, false, true);
171
-			return $response;
172
-		} catch (NotFoundException $e) {
173
-			// If we have no preview enabled, we can redirect to the mime icon if any
174
-			if ($mimeFallback) {
175
-				if ($url = $this->mimeIconProvider->getMimeIconUrl($node->getMimeType())) {
176
-					return new RedirectResponse($url);
177
-				}
178
-			}
179
-
180
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
181
-		} catch (\InvalidArgumentException $e) {
182
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
183
-		}
184
-	}
185
-
186
-	/**
187
-	 * Get a preview by mime
188
-	 *
189
-	 * @param string $mime Mime type
190
-	 * @return RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
191
-	 *
192
-	 * 303: The mime icon url
193
-	 */
194
-	#[NoCSRFRequired]
195
-	#[PublicPage]
196
-	#[FrontpageRoute(verb: 'GET', url: '/core/mimeicon')]
197
-	#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
198
-	public function getMimeIconUrl(string $mime = 'application/octet-stream') {
199
-		$url = $this->mimeIconProvider->getMimeIconUrl($mime);
200
-		if ($url === null) {
201
-			$url = $this->mimeIconProvider->getMimeIconUrl('application/octet-stream');
202
-		}
203
-
204
-		return new RedirectResponse($url);
205
-	}
32
+    public function __construct(
33
+        string $appName,
34
+        IRequest $request,
35
+        private IPreview $preview,
36
+        private IRootFolder $root,
37
+        private ?string $userId,
38
+        private IMimeIconProvider $mimeIconProvider,
39
+    ) {
40
+        parent::__construct($appName, $request);
41
+    }
42
+
43
+    /**
44
+     * Get a preview by file path
45
+     *
46
+     * @param string $file Path of the file
47
+     * @param int $x Width of the preview. A width of -1 will use the original image width.
48
+     * @param int $y Height of the preview. A height of -1 will use the original image height.
49
+     * @param bool $a Preserve the aspect ratio
50
+     * @param bool $forceIcon Force returning an icon
51
+     * @param 'fill'|'cover' $mode How to crop the image
52
+     * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
53
+     * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
54
+     *
55
+     * 200: Preview returned
56
+     * 303: Redirect to the mime icon url if mimeFallback is true
57
+     * 400: Getting preview is not possible
58
+     * 403: Getting preview is not allowed
59
+     * 404: Preview not found
60
+     */
61
+    #[NoAdminRequired]
62
+    #[NoCSRFRequired]
63
+    #[FrontpageRoute(verb: 'GET', url: '/core/preview.png')]
64
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
65
+    public function getPreview(
66
+        string $file = '',
67
+        int $x = 32,
68
+        int $y = 32,
69
+        bool $a = false,
70
+        bool $forceIcon = true,
71
+        string $mode = 'fill',
72
+        bool $mimeFallback = false): Response {
73
+        if ($file === '' || $x === 0 || $y === 0) {
74
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
75
+        }
76
+
77
+        try {
78
+            $userFolder = $this->root->getUserFolder($this->userId);
79
+            $node = $userFolder->get($file);
80
+        } catch (NotFoundException $e) {
81
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
82
+        }
83
+
84
+        return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback);
85
+    }
86
+
87
+    /**
88
+     * Get a preview by file ID
89
+     *
90
+     * @param int $fileId ID of the file
91
+     * @param int $x Width of the preview. A width of -1 will use the original image width.
92
+     * @param int $y Height of the preview. A height of -1 will use the original image height.
93
+     * @param bool $a Preserve the aspect ratio
94
+     * @param bool $forceIcon Force returning an icon
95
+     * @param 'fill'|'cover' $mode How to crop the image
96
+     * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
97
+     * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
98
+     *
99
+     * 200: Preview returned
100
+     * 303: Redirect to the mime icon url if mimeFallback is true
101
+     * 400: Getting preview is not possible
102
+     * 403: Getting preview is not allowed
103
+     * 404: Preview not found
104
+     */
105
+    #[NoAdminRequired]
106
+    #[NoCSRFRequired]
107
+    #[FrontpageRoute(verb: 'GET', url: '/core/preview')]
108
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
109
+    public function getPreviewByFileId(
110
+        int $fileId = -1,
111
+        int $x = 32,
112
+        int $y = 32,
113
+        bool $a = false,
114
+        bool $forceIcon = true,
115
+        string $mode = 'fill',
116
+        bool $mimeFallback = false) {
117
+        if ($fileId === -1 || $x === 0 || $y === 0) {
118
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
119
+        }
120
+
121
+        $userFolder = $this->root->getUserFolder($this->userId);
122
+        $node = $userFolder->getFirstNodeById($fileId);
123
+
124
+        if (!$node) {
125
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
126
+        }
127
+
128
+        return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback);
129
+    }
130
+
131
+    /**
132
+     * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
133
+     */
134
+    private function fetchPreview(
135
+        Node $node,
136
+        int $x,
137
+        int $y,
138
+        bool $a,
139
+        bool $forceIcon,
140
+        string $mode,
141
+        bool $mimeFallback = false) : Response {
142
+        if (!($node instanceof File) || (!$forceIcon && !$this->preview->isAvailable($node))) {
143
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
144
+        }
145
+        if (!$node->isReadable()) {
146
+            return new DataResponse([], Http::STATUS_FORBIDDEN);
147
+        }
148
+
149
+        if ($node->getId() <= 0) {
150
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
151
+        }
152
+
153
+        // Is this header is set it means our UI is doing a preview for no-download shares
154
+        // we check a header so we at least prevent people from using the link directly (obfuscation)
155
+        $isNextcloudPreview = $this->request->getHeader('x-nc-preview') === 'true';
156
+        $storage = $node->getStorage();
157
+        if ($isNextcloudPreview === false && $storage->instanceOfStorage(ISharedStorage::class)) {
158
+            /** @var ISharedStorage $storage */
159
+            $share = $storage->getShare();
160
+            if (!$share->canSeeContent()) {
161
+                return new DataResponse([], Http::STATUS_FORBIDDEN);
162
+            }
163
+        }
164
+
165
+        try {
166
+            $f = $this->preview->getPreview($node, $x, $y, !$a, $mode);
167
+            $response = new FileDisplayResponse($f, Http::STATUS_OK, [
168
+                'Content-Type' => $f->getMimeType(),
169
+            ]);
170
+            $response->cacheFor(3600 * 24, false, true);
171
+            return $response;
172
+        } catch (NotFoundException $e) {
173
+            // If we have no preview enabled, we can redirect to the mime icon if any
174
+            if ($mimeFallback) {
175
+                if ($url = $this->mimeIconProvider->getMimeIconUrl($node->getMimeType())) {
176
+                    return new RedirectResponse($url);
177
+                }
178
+            }
179
+
180
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
181
+        } catch (\InvalidArgumentException $e) {
182
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
183
+        }
184
+    }
185
+
186
+    /**
187
+     * Get a preview by mime
188
+     *
189
+     * @param string $mime Mime type
190
+     * @return RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
191
+     *
192
+     * 303: The mime icon url
193
+     */
194
+    #[NoCSRFRequired]
195
+    #[PublicPage]
196
+    #[FrontpageRoute(verb: 'GET', url: '/core/mimeicon')]
197
+    #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
198
+    public function getMimeIconUrl(string $mime = 'application/octet-stream') {
199
+        $url = $this->mimeIconProvider->getMimeIconUrl($mime);
200
+        if ($url === null) {
201
+            $url = $this->mimeIconProvider->getMimeIconUrl('application/octet-stream');
202
+        }
203
+
204
+        return new RedirectResponse($url);
205
+    }
206 206
 }
Please login to merge, or discard this patch.