Browse Source

fix: Check if user is authorized to use the files they mentioned

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
pull/45094/head
Marcel Klehr 2 years ago
parent
commit
6203c1c7da
  1. 17
      core/Controller/TaskProcessingApiController.php
  2. 30
      lib/private/TaskProcessing/Manager.php
  3. 10
      lib/public/TaskProcessing/Exception/PreConditionNotMetException.php
  4. 10
      lib/public/TaskProcessing/Exception/UnauthorizedException.php
  5. 4
      lib/public/TaskProcessing/IManager.php

17
core/Controller/TaskProcessingApiController.php

@ -46,6 +46,7 @@ use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
use OCP\TaskProcessing\EShapeType;
use OCP\TaskProcessing\Exception\Exception;
use OCP\TaskProcessing\Exception\UnauthorizedException;
use OCP\TaskProcessing\Exception\ValidationException;
use OCP\TaskProcessing\ShapeDescriptor;
use OCP\TaskProcessing\Task;
@ -124,10 +125,12 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
return new DataResponse([
'task' => $json,
]);
} catch (PreConditionNotMetException) {
} catch (\OCP\TaskProcessing\Exception\PreConditionNotMetException) {
return new DataResponse(['message' => $this->l->t('The given provider is not available')], Http::STATUS_PRECONDITION_FAILED);
} catch (ValidationException $e) {
return new DataResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
} catch (UnauthorizedException $e) {
return new DataResponse(['message' => 'User does not have access to the files mentioned in the task input'], Http::STATUS_UNAUTHORIZED);
} catch (\OCP\TaskProcessing\Exception\Exception $e) {
return new DataResponse(['message' => 'Internal server error'], Http::STATUS_INTERNAL_SERVER_ERROR);
}
@ -269,13 +272,21 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
$taskType = $taskTypes[$task->getTaskTypeId()];
foreach ($taskType['inputShape'] + $taskType['optionalInputShape'] as $key => $descriptor) {
if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
$ids[] = $task->getInput()[$key];
if (is_array($task->getInput()[$key])) {
$ids += $task->getInput()[$key];
} else {
$ids[] = $task->getInput()[$key];
}
}
}
if ($task->getOutput() !== null) {
foreach ($taskType['outputShape'] + $taskType['optionalOutputShape'] as $key => $descriptor) {
if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
$ids[] = $task->getOutput()[$key];
if (is_array($task->getInput()[$key])) {
$ids += $task->getOutput()[$key];
} else {
$ids[] = $task->getOutput()[$key];
}
}
}
}

30
lib/private/TaskProcessing/Manager.php

@ -52,6 +52,7 @@ use OCP\TaskProcessing\Events\TaskFailedEvent;
use OCP\TaskProcessing\Events\TaskSuccessfulEvent;
use OCP\TaskProcessing\Exception\NotFoundException;
use OCP\TaskProcessing\Exception\ProcessingException;
use OCP\TaskProcessing\Exception\UnauthorizedException;
use OCP\TaskProcessing\Exception\ValidationException;
use OCP\TaskProcessing\IManager;
use OCP\TaskProcessing\IProvider;
@ -93,6 +94,7 @@ class Manager implements IManager {
private \OCP\TextProcessing\IManager $textProcessingManager,
private \OCP\TextToImage\IManager $textToImageManager,
private \OCP\SpeechToText\ISpeechToTextManager $speechToTextManager,
private \OCP\Share\IManager $shareManager,
) {
$this->appData = $appDataFactory->get('core');
}
@ -553,7 +555,7 @@ class Manager implements IManager {
public function scheduleTask(Task $task): void {
if (!$this->canHandleTask($task)) {
throw new PreConditionNotMetException('No task processing provider is installed that can handle this task type: ' . $task->getTaskTypeId());
throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('No task processing provider is installed that can handle this task type: ' . $task->getTaskTypeId());
}
$taskTypes = $this->getAvailableTaskTypes();
$inputShape = $taskTypes[$task->getTaskTypeId()]['inputShape'];
@ -561,6 +563,32 @@ class Manager implements IManager {
// validate input
$this->validateInput($inputShape, $task->getInput());
$this->validateInput($optionalInputShape, $task->getInput(), true);
// authenticate access to mentioned files
$ids = [];
foreach ($inputShape + $optionalInputShape as $key => $descriptor) {
if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
if (is_array($task->getInput()[$key])) {
$ids += $task->getInput()[$key];
} else {
$ids[] = $task->getInput()[$key];
}
}
}
foreach ($ids as $fileId) {
$node = $this->rootFolder->getFirstNodeById($fileId);
if ($node === null) {
$node = $this->rootFolder->getFirstNodeByIdInPath($fileId, '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
if ($node === null) {
throw new ValidationException('Could not find file ' . $fileId);
}
}
/** @var array{users:array<string,array{node_id:int, node_path: string}>, remote: array<string,array{node_id:int, node_path: string}>, mail: array<string,array{node_id:int, node_path: string}>} $accessList */
$accessList = $this->shareManager->getAccessList($node, true, true);
$userIds = array_map(fn ($id) => strval($id), array_keys($accessList['users']));
if (!in_array($task->getUserId(), $userIds)) {
throw new UnauthorizedException('User ' . $task->getUserId() . ' does not have access to file ' . $fileId);
}
}
// remove superfluous keys and set input
$task->setInput($this->removeSuperfluousArrayKeys($task->getInput(), $inputShape, $optionalInputShape));
$task->setStatus(Task::STATUS_SCHEDULED);

10
lib/public/TaskProcessing/Exception/PreConditionNotMetException.php

@ -0,0 +1,10 @@
<?php
namespace OCP\TaskProcessing\Exception;
/**
* @since 30.0.0
*/
class PreConditionNotMetException extends Exception {
}

10
lib/public/TaskProcessing/Exception/UnauthorizedException.php

@ -0,0 +1,10 @@
<?php
namespace OCP\TaskProcessing\Exception;
/**
* @since 30.0.0
*/
class UnauthorizedException extends Exception {
}

4
lib/public/TaskProcessing/IManager.php

@ -29,9 +29,10 @@ namespace OCP\TaskProcessing;
use OCP\Files\GenericFileException;
use OCP\Files\NotPermittedException;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
use OCP\TaskProcessing\Exception\PreConditionNotMetException;
use OCP\TaskProcessing\Exception\Exception;
use OCP\TaskProcessing\Exception\NotFoundException;
use OCP\TaskProcessing\Exception\UnauthorizedException;
use OCP\TaskProcessing\Exception\ValidationException;
/**
@ -62,6 +63,7 @@ interface IManager {
* @throws PreConditionNotMetException If no or not the requested provider was registered but this method was still called
* @throws ValidationException the given task input didn't pass validation against the task type's input shape and/or the providers optional input shape specs
* @throws Exception storing the task in the database failed
* @throws UnauthorizedException the user scheduling the task does not have access to the files used in the input
* @since 30.0.0
*/
public function scheduleTask(Task $task): void;

Loading…
Cancel
Save