Skip to content

Commit 13921ca

Browse files
Merge pull request #46807 from nextcloud/refactor/files/security-attributes
2 parents 60b9bb4 + 3fde60d commit 13921ca

7 files changed

Lines changed: 56 additions & 73 deletions

apps/files/lib/Controller/ApiController.php

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
use OCA\Files\Service\ViewConfig;
1414
use OCP\AppFramework\Controller;
1515
use OCP\AppFramework\Http;
16+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
17+
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
1618
use OCP\AppFramework\Http\Attribute\OpenAPI;
19+
use OCP\AppFramework\Http\Attribute\PublicPage;
20+
use OCP\AppFramework\Http\Attribute\StrictCookiesRequired;
1721
use OCP\AppFramework\Http\ContentSecurityPolicy;
1822
use OCP\AppFramework\Http\DataResponse;
1923
use OCP\AppFramework\Http\FileDisplayResponse;
@@ -69,10 +73,6 @@ public function __construct(string $appName,
6973
*
7074
* @since API version 1.0
7175
*
72-
* @NoAdminRequired
73-
* @NoCSRFRequired
74-
* @StrictCookieRequired
75-
*
7676
* @param int $x Width of the thumbnail
7777
* @param int $y Height of the thumbnail
7878
* @param string $file URL-encoded filename
@@ -82,6 +82,9 @@ public function __construct(string $appName,
8282
* 400: Getting thumbnail is not possible
8383
* 404: File not found
8484
*/
85+
#[NoAdminRequired]
86+
#[NoCSRFRequired]
87+
#[StrictCookiesRequired]
8588
public function getThumbnail($x, $y, $file) {
8689
if ($x < 1 || $y < 1) {
8790
return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
@@ -113,12 +116,11 @@ public function getThumbnail($x, $y, $file) {
113116
* The passed tags are absolute, which means they will
114117
* replace the actual tag selection.
115118
*
116-
* @NoAdminRequired
117-
*
118119
* @param string $path path
119120
* @param array|string $tags array of tags
120121
* @return DataResponse
121122
*/
123+
#[NoAdminRequired]
122124
public function updateFileTags($path, $tags = null) {
123125
$result = [];
124126
// if tags specified or empty array, update tags
@@ -221,10 +223,9 @@ private function getShareTypesForNodes(array $nodes): array {
221223
/**
222224
* Returns a list of recently modified files.
223225
*
224-
* @NoAdminRequired
225-
*
226226
* @return DataResponse
227227
*/
228+
#[NoAdminRequired]
228229
public function getRecentFiles() {
229230
$nodes = $this->userFolder->getRecent(100);
230231
$files = $this->formatNodes($nodes);
@@ -235,11 +236,10 @@ public function getRecentFiles() {
235236
/**
236237
* Returns the current logged-in user's storage stats.
237238
*
238-
* @NoAdminRequired
239-
*
240239
* @param ?string $dir the directory to get the storage stats from
241240
* @return JSONResponse
242241
*/
242+
#[NoAdminRequired]
243243
public function getStorageStats($dir = '/'): JSONResponse {
244244
$storageInfo = \OC_Helper::getStorageInfo($dir ?: '/');
245245
$response = new JSONResponse(['message' => 'ok', 'data' => $storageInfo]);
@@ -250,13 +250,12 @@ public function getStorageStats($dir = '/'): JSONResponse {
250250
/**
251251
* Set a user view config
252252
*
253-
* @NoAdminRequired
254-
*
255253
* @param string $view
256254
* @param string $key
257255
* @param string|bool $value
258256
* @return JSONResponse
259257
*/
258+
#[NoAdminRequired]
260259
public function setViewConfig(string $view, string $key, $value): JSONResponse {
261260
try {
262261
$this->viewConfig->setConfig($view, $key, (string)$value);
@@ -271,23 +270,21 @@ public function setViewConfig(string $view, string $key, $value): JSONResponse {
271270
/**
272271
* Get the user view config
273272
*
274-
* @NoAdminRequired
275-
*
276273
* @return JSONResponse
277274
*/
275+
#[NoAdminRequired]
278276
public function getViewConfigs(): JSONResponse {
279277
return new JSONResponse(['message' => 'ok', 'data' => $this->viewConfig->getConfigs()]);
280278
}
281279

282280
/**
283281
* Set a user config
284282
*
285-
* @NoAdminRequired
286-
*
287283
* @param string $key
288284
* @param string|bool $value
289285
* @return JSONResponse
290286
*/
287+
#[NoAdminRequired]
291288
public function setConfig(string $key, $value): JSONResponse {
292289
try {
293290
$this->userConfig->setConfig($key, (string)$value);
@@ -302,23 +299,21 @@ public function setConfig(string $key, $value): JSONResponse {
302299
/**
303300
* Get the user config
304301
*
305-
* @NoAdminRequired
306-
*
307302
* @return JSONResponse
308303
*/
304+
#[NoAdminRequired]
309305
public function getConfigs(): JSONResponse {
310306
return new JSONResponse(['message' => 'ok', 'data' => $this->userConfig->getConfigs()]);
311307
}
312308

313309
/**
314310
* Toggle default for showing/hiding hidden files
315311
*
316-
* @NoAdminRequired
317-
*
318312
* @param bool $value
319313
* @return Response
320314
* @throws \OCP\PreConditionNotMetException
321315
*/
316+
#[NoAdminRequired]
322317
public function showHiddenFiles(bool $value): Response {
323318
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', $value ? '1' : '0');
324319
return new Response();
@@ -327,12 +322,11 @@ public function showHiddenFiles(bool $value): Response {
327322
/**
328323
* Toggle default for cropping preview images
329324
*
330-
* @NoAdminRequired
331-
*
332325
* @param bool $value
333326
* @return Response
334327
* @throws \OCP\PreConditionNotMetException
335328
*/
329+
#[NoAdminRequired]
336330
public function cropImagePreviews(bool $value): Response {
337331
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', $value ? '1' : '0');
338332
return new Response();
@@ -341,32 +335,27 @@ public function cropImagePreviews(bool $value): Response {
341335
/**
342336
* Toggle default for files grid view
343337
*
344-
* @NoAdminRequired
345-
*
346338
* @param bool $show
347339
* @return Response
348340
* @throws \OCP\PreConditionNotMetException
349341
*/
342+
#[NoAdminRequired]
350343
public function showGridView(bool $show): Response {
351344
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', $show ? '1' : '0');
352345
return new Response();
353346
}
354347

355348
/**
356349
* Get default settings for the grid view
357-
*
358-
* @NoAdminRequired
359350
*/
351+
#[NoAdminRequired]
360352
public function getGridView() {
361353
$status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '0') === '1';
362354
return new JSONResponse(['gridview' => $status]);
363355
}
364356

365-
/**
366-
* @NoAdminRequired
367-
* @NoCSRFRequired
368-
* @PublicPage
369-
*/
357+
#[PublicPage]
358+
#[NoCSRFRequired]
370359
#[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
371360
public function serviceWorker(): StreamResponse {
372361
$response = new StreamResponse(__DIR__ . '/../../../../dist/preview-service-worker.js');

apps/files/lib/Controller/DirectEditingController.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Exception;
99
use OCA\Files\Service\DirectEditingService;
1010
use OCP\AppFramework\Http;
11+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
1112
use OCP\AppFramework\Http\DataResponse;
1213
use OCP\AppFramework\OCSController;
1314
use OCP\DirectEditing\IManager;
@@ -34,22 +35,19 @@ public function __construct(
3435
}
3536

3637
/**
37-
* @NoAdminRequired
38-
*
3938
* Get the direct editing capabilities
4039
* @return DataResponse<Http::STATUS_OK, array{editors: array<string, array{id: string, name: string, mimetypes: string[], optionalMimetypes: string[], secure: bool}>, creators: array<string, array{id: string, editor: string, name: string, extension: string, templates: bool, mimetypes: string[]}>}, array{}>
4140
*
4241
* 200: Direct editing capabilities returned
4342
*/
43+
#[NoAdminRequired]
4444
public function info(): DataResponse {
4545
$response = new DataResponse($this->directEditingService->getDirectEditingCapabilitites());
4646
$response->setETag($this->directEditingService->getDirectEditingETag());
4747
return $response;
4848
}
4949

5050
/**
51-
* @NoAdminRequired
52-
*
5351
* Create a file for direct editing
5452
*
5553
* @param string $path Path of the file
@@ -62,6 +60,7 @@ public function info(): DataResponse {
6260
* 200: URL for direct editing returned
6361
* 403: Opening file is not allowed
6462
*/
63+
#[NoAdminRequired]
6564
public function create(string $path, string $editorId, string $creatorId, ?string $templateId = null): DataResponse {
6665
if (!$this->directEditingManager->isEnabled()) {
6766
return new DataResponse(['message' => 'Direct editing is not enabled'], Http::STATUS_INTERNAL_SERVER_ERROR);
@@ -85,8 +84,6 @@ public function create(string $path, string $editorId, string $creatorId, ?strin
8584
}
8685

8786
/**
88-
* @NoAdminRequired
89-
*
9087
* Open a file for direct editing
9188
*
9289
* @param string $path Path of the file
@@ -98,6 +95,7 @@ public function create(string $path, string $editorId, string $creatorId, ?strin
9895
* 200: URL for direct editing returned
9996
* 403: Opening file is not allowed
10097
*/
98+
#[NoAdminRequired]
10199
public function open(string $path, ?string $editorId = null, ?int $fileId = null): DataResponse {
102100
if (!$this->directEditingManager->isEnabled()) {
103101
return new DataResponse(['message' => 'Direct editing is not enabled'], Http::STATUS_INTERNAL_SERVER_ERROR);
@@ -123,8 +121,6 @@ public function open(string $path, ?string $editorId = null, ?int $fileId = null
123121

124122

125123
/**
126-
* @NoAdminRequired
127-
*
128124
* Get the templates for direct editing
129125
*
130126
* @param string $editorId ID of the editor
@@ -134,6 +130,7 @@ public function open(string $path, ?string $editorId = null, ?int $fileId = null
134130
*
135131
* 200: Templates returned
136132
*/
133+
#[NoAdminRequired]
137134
public function templates(string $editorId, string $creatorId): DataResponse {
138135
if (!$this->directEditingManager->isEnabled()) {
139136
return new DataResponse(['message' => 'Direct editing is not enabled'], Http::STATUS_INTERNAL_SERVER_ERROR);

apps/files/lib/Controller/DirectEditingViewController.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
use Exception;
99
use OCP\AppFramework\Controller;
10+
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
1011
use OCP\AppFramework\Http\Attribute\OpenAPI;
12+
use OCP\AppFramework\Http\Attribute\PublicPage;
13+
use OCP\AppFramework\Http\Attribute\UseSession;
1114
use OCP\AppFramework\Http\NotFoundResponse;
1215
use OCP\AppFramework\Http\Response;
1316
use OCP\DirectEditing\IManager;
@@ -29,13 +32,12 @@ public function __construct(
2932
}
3033

3134
/**
32-
* @PublicPage
33-
* @NoCSRFRequired
34-
* @UseSession
35-
*
3635
* @param string $token
3736
* @return Response
3837
*/
38+
#[PublicPage]
39+
#[NoCSRFRequired]
40+
#[UseSession]
3941
public function edit(string $token): Response {
4042
$this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager));
4143
try {

apps/files/lib/Controller/OpenLocalEditorController.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
use OCA\Files\Db\OpenLocalEditorMapper;
1414
use OCP\AppFramework\Db\DoesNotExistException;
1515
use OCP\AppFramework\Http;
16+
use OCP\AppFramework\Http\Attribute\BruteForceProtection;
17+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
18+
use OCP\AppFramework\Http\Attribute\UserRateLimit;
1619
use OCP\AppFramework\Http\DataResponse;
1720
use OCP\AppFramework\OCSController;
1821
use OCP\AppFramework\Utility\ITimeFactory;
@@ -51,9 +54,6 @@ public function __construct(
5154
}
5255

5356
/**
54-
* @NoAdminRequired
55-
* @UserRateThrottle(limit=10, period=120)
56-
*
5757
* Create a local editor
5858
*
5959
* @param string $path Path of the file
@@ -62,6 +62,8 @@ public function __construct(
6262
*
6363
* 200: Local editor returned
6464
*/
65+
#[NoAdminRequired]
66+
#[UserRateLimit(limit: 10, period: 120)]
6567
public function create(string $path): DataResponse {
6668
$pathHash = sha1($path);
6769

@@ -96,9 +98,6 @@ public function create(string $path): DataResponse {
9698
}
9799

98100
/**
99-
* @NoAdminRequired
100-
* @BruteForceProtection(action=openLocalEditor)
101-
*
102101
* Validate a local editor
103102
*
104103
* @param string $path Path of the file
@@ -109,6 +108,8 @@ public function create(string $path): DataResponse {
109108
* 200: Local editor validated successfully
110109
* 404: Local editor not found
111110
*/
111+
#[NoAdminRequired]
112+
#[BruteForceProtection(action: 'openLocalEditor')]
112113
public function validate(string $path, string $token): DataResponse {
113114
$pathHash = sha1($path);
114115

apps/files/lib/Controller/TemplateController.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use OCA\Files\ResponseDefinitions;
1212
use OCP\AppFramework\Http;
13+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
1314
use OCP\AppFramework\Http\DataResponse;
1415
use OCP\AppFramework\OCS\OCSForbiddenException;
1516
use OCP\AppFramework\OCSController;
@@ -32,21 +33,18 @@ public function __construct($appName, IRequest $request, ITemplateManager $templ
3233
}
3334

3435
/**
35-
* @NoAdminRequired
36-
*
3736
* List the available templates
3837
*
3938
* @return DataResponse<Http::STATUS_OK, array<FilesTemplateFileCreator>, array{}>
4039
*
4140
* 200: Available templates returned
4241
*/
42+
#[NoAdminRequired]
4343
public function list(): DataResponse {
4444
return new DataResponse($this->templateManager->listTemplates());
4545
}
4646

4747
/**
48-
* @NoAdminRequired
49-
*
5048
* Create a template
5149
*
5250
* @param string $filePath Path of the file
@@ -59,6 +57,7 @@ public function list(): DataResponse {
5957
*
6058
* 200: Template created successfully
6159
*/
60+
#[NoAdminRequired]
6261
public function create(
6362
string $filePath,
6463
string $templatePath = '',
@@ -77,8 +76,6 @@ public function create(
7776
}
7877

7978
/**
80-
* @NoAdminRequired
81-
*
8279
* Initialize the template directory
8380
*
8481
* @param string $templatePath Path of the template directory
@@ -89,6 +86,7 @@ public function create(
8986
*
9087
* 200: Template directory initialized successfully
9188
*/
89+
#[NoAdminRequired]
9290
public function path(string $templatePath = '', bool $copySystemTemplates = false) {
9391
try {
9492
/** @var string $templatePath */

0 commit comments

Comments
 (0)