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 1 month ago
parent
commit
6203c1c7da

+ 14
- 3
core/Controller/TaskProcessingApiController.php View File

@@ -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];
}
}
}
}

+ 29
- 1
lib/private/TaskProcessing/Manager.php View File

@@ -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
- 0
lib/public/TaskProcessing/Exception/PreConditionNotMetException.php View File

@@ -0,0 +1,10 @@
<?php

namespace OCP\TaskProcessing\Exception;

/**
* @since 30.0.0
*/
class PreConditionNotMetException extends Exception {

}

+ 10
- 0
lib/public/TaskProcessing/Exception/UnauthorizedException.php View File

@@ -0,0 +1,10 @@
<?php

namespace OCP\TaskProcessing\Exception;

/**
* @since 30.0.0
*/
class UnauthorizedException extends Exception {

}

+ 3
- 1
lib/public/TaskProcessing/IManager.php View File

@@ -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