aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorMarcel Klehr <mklehr@gmx.net>2024-05-15 11:43:08 +0200
committerGitHub <noreply@github.com>2024-05-15 11:43:08 +0200
commitf3e72aff7c0dec5934c1c797ec301ea0e4f4253b (patch)
treec254e43d15b7cd8fb6175c6da0b3e0302200a42f /core
parentc1e73303dbfa3a238bb1745c73e9553fedaab1f8 (diff)
parent6c4992de54d7ce78ff19f588d403162b0c8f580a (diff)
downloadnextcloud-server-f3e72aff7c0dec5934c1c797ec301ea0e4f4253b.tar.gz
nextcloud-server-f3e72aff7c0dec5934c1c797ec301ea0e4f4253b.zip
Merge pull request #45094 from nextcloud/enh/taskprocessing-api
feat: TaskProcessing API
Diffstat (limited to 'core')
-rw-r--r--core/Controller/TaskProcessingApiController.php430
-rw-r--r--core/Migrations/Version30000Date20240429122720.php115
-rw-r--r--core/ResponseDefinitions.php31
-rw-r--r--core/openapi.json1640
4 files changed, 2216 insertions, 0 deletions
diff --git a/core/Controller/TaskProcessingApiController.php b/core/Controller/TaskProcessingApiController.php
new file mode 100644
index 00000000000..ce89ebd34bb
--- /dev/null
+++ b/core/Controller/TaskProcessingApiController.php
@@ -0,0 +1,430 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2024 Marcel Klehr <mklehr@gmx.net>
+ *
+ * @author Marcel Klehr <mklehr@gmx.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+namespace OC\Core\Controller;
+
+use OCA\Core\ResponseDefinitions;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\AnonRateLimit;
+use OCP\AppFramework\Http\Attribute\ApiRoute;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PublicPage;
+use OCP\AppFramework\Http\Attribute\UserRateLimit;
+use OCP\AppFramework\Http\DataDownloadResponse;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\Common\Exception\NotFoundException;
+use OCP\Files\File;
+use OCP\Files\GenericFileException;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotPermittedException;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\Lock\LockedException;
+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;
+
+/**
+ * @psalm-import-type CoreTaskProcessingTask from ResponseDefinitions
+ * @psalm-import-type CoreTaskProcessingTaskType from ResponseDefinitions
+ */
+class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private \OCP\TaskProcessing\IManager $taskProcessingManager,
+ private IL10N $l,
+ private ?string $userId,
+ private IRootFolder $rootFolder,
+ ) {
+ parent::__construct($appName, $request);
+ }
+
+ /**
+ * This endpoint returns all available TaskProcessing task types
+ *
+ * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
+ *
+ * 200: Task types returned
+ */
+ #[PublicPage]
+ #[ApiRoute(verb: 'GET', url: '/tasktypes', root: '/taskprocessing')]
+ public function taskTypes(): DataResponse {
+ $taskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
+
+ $serializedTaskTypes = [];
+ foreach ($taskTypes as $key => $taskType) {
+ $serializedTaskTypes[$key] = [
+ 'name' => $taskType['name'],
+ 'description' => $taskType['description'],
+ 'inputShape' => array_map(fn (ShapeDescriptor $descriptor) =>
+ $descriptor->jsonSerialize() + ['mandatory' => true], $taskType['inputShape'])
+ + array_map(fn (ShapeDescriptor $descriptor) =>
+ $descriptor->jsonSerialize() + ['mandatory' => false], $taskType['optionalInputShape']),
+ 'outputShape' => array_map(fn (ShapeDescriptor $descriptor) =>
+ $descriptor->jsonSerialize() + ['mandatory' => true], $taskType['outputShape'])
+ + array_map(fn (ShapeDescriptor $descriptor) =>
+ $descriptor->jsonSerialize() + ['mandatory' => false], $taskType['optionalOutputShape']),
+ ];
+ }
+
+ return new DataResponse([
+ 'types' => $serializedTaskTypes,
+ ]);
+ }
+
+ /**
+ * This endpoint allows scheduling a task
+ *
+ * @param array<string, mixed> $input Task's input parameters
+ * @param string $type Type of the task
+ * @param string $appId ID of the app that will execute the task
+ * @param string $customId An arbitrary identifier for the task
+ *
+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED|Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>
+ *
+ * 200: Task scheduled successfully
+ * 400: Scheduling task is not possible
+ * 412: Scheduling task is not possible
+ * 401: Cannot schedule task because it references files in its input that the user doesn't have access to
+ */
+ #[PublicPage]
+ #[UserRateLimit(limit: 20, period: 120)]
+ #[AnonRateLimit(limit: 5, period: 120)]
+ #[ApiRoute(verb: 'POST', url: '/schedule', root: '/taskprocessing')]
+ public function schedule(array $input, string $type, string $appId, string $customId = ''): DataResponse {
+ $task = new Task($type, $input, $appId, $this->userId, $customId);
+ try {
+ $this->taskProcessingManager->scheduleTask($task);
+
+ /** @var CoreTaskProcessingTask $json */
+ $json = $task->jsonSerialize();
+
+ return new DataResponse([
+ 'task' => $json,
+ ]);
+ } 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);
+ }
+ }
+
+ /**
+ * This endpoint allows checking the status and results of a task.
+ * Tasks are removed 1 week after receiving their last update
+ *
+ * @param int $id The id of the task
+ *
+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
+ *
+ * 200: Task returned
+ * 404: Task not found
+ */
+ #[PublicPage]
+ #[ApiRoute(verb: 'GET', url: '/task/{id}', root: '/taskprocessing')]
+ public function getTask(int $id): DataResponse {
+ try {
+ $task = $this->taskProcessingManager->getUserTask($id, $this->userId);
+
+ /** @var CoreTaskProcessingTask $json */
+ $json = $task->jsonSerialize();
+
+ return new DataResponse([
+ 'task' => $json,
+ ]);
+ } catch (NotFoundException $e) {
+ return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
+ } catch (\RuntimeException $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This endpoint allows to delete a scheduled task for a user
+ *
+ * @param int $id The id of the task
+ *
+ * @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
+ *
+ * 200: Task returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'DELETE', url: '/task/{id}', root: '/taskprocessing')]
+ public function deleteTask(int $id): DataResponse {
+ try {
+ $task = $this->taskProcessingManager->getUserTask($id, $this->userId);
+
+ $this->taskProcessingManager->deleteTask($task);
+
+ return new DataResponse(null);
+ } catch (\OCP\TaskProcessing\Exception\NotFoundException $e) {
+ return new DataResponse(null);
+ } catch (\OCP\TaskProcessing\Exception\Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+
+ /**
+ * This endpoint returns a list of tasks of a user that are related
+ * with a specific appId and optionally with an identifier
+ *
+ * @param string $appId ID of the app
+ * @param string|null $customId An arbitrary identifier for the task
+ * @return DataResponse<Http::STATUS_OK, array{tasks: CoreTaskProcessingTask[]}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
+ *
+ * 200: Task list returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/tasks/app/{appId}', root: '/taskprocessing')]
+ public function listTasksByApp(string $appId, ?string $customId = null): DataResponse {
+ try {
+ $tasks = $this->taskProcessingManager->getUserTasksByApp($this->userId, $appId, $customId);
+ /** @var CoreTaskProcessingTask[] $json */
+ $json = array_map(static function (Task $task) {
+ return $task->jsonSerialize();
+ }, $tasks);
+
+ return new DataResponse([
+ 'tasks' => $json,
+ ]);
+ } catch (Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ } catch (\JsonException $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This endpoint returns a list of tasks of a user that are related
+ * with a specific appId and optionally with an identifier
+ *
+ * @param string|null $taskType The task type to filter by
+ * @param string|null $customId An arbitrary identifier for the task
+ * @return DataResponse<Http::STATUS_OK, array{tasks: CoreTaskProcessingTask[]}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
+ *
+ * 200: Task list returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/tasks', root: '/taskprocessing')]
+ public function listTasksByUser(?string $taskType, ?string $customId = null): DataResponse {
+ try {
+ $tasks = $this->taskProcessingManager->getUserTasks($this->userId, $taskType, $customId);
+ /** @var CoreTaskProcessingTask[] $json */
+ $json = array_map(static function (Task $task) {
+ return $task->jsonSerialize();
+ }, $tasks);
+
+ return new DataResponse([
+ 'tasks' => $json,
+ ]);
+ } catch (Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ } catch (\JsonException $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This endpoint returns the contents of a file referenced in a task
+ *
+ * @param int $taskId The id of the task
+ * @param int $fileId The file id of the file to retrieve
+ * @return DataDownloadResponse<Http::STATUS_OK, string, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
+ *
+ * 200: File content returned
+ * 404: Task or file not found
+ */
+ #[NoAdminRequired]
+ #[Http\Attribute\NoCSRFRequired]
+ #[ApiRoute(verb: 'GET', url: '/tasks/{taskId}/file/{fileId}', root: '/taskprocessing')]
+ public function getFileContents(int $taskId, int $fileId): Http\DataDownloadResponse|DataResponse {
+ try {
+ $task = $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+ $ids = $this->extractFileIdsFromTask($task);
+ if (!in_array($fileId, $ids)) {
+ return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND);
+ }
+ $node = $this->rootFolder->getFirstNodeById($fileId);
+ if ($node === null) {
+ $node = $this->rootFolder->getFirstNodeByIdInPath($fileId, '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
+ if (!$node instanceof File) {
+ throw new \OCP\TaskProcessing\Exception\NotFoundException('Node is not a file');
+ }
+ } elseif (!$node instanceof File) {
+ throw new \OCP\TaskProcessing\Exception\NotFoundException('Node is not a file');
+ }
+ return new Http\DataDownloadResponse($node->getContent(), $node->getName(), $node->getMimeType());
+ } catch (\OCP\TaskProcessing\Exception\NotFoundException $e) {
+ return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND);
+ } catch (GenericFileException|NotPermittedException|LockedException|Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * @param Task $task
+ * @return list<int>
+ * @throws \OCP\TaskProcessing\Exception\NotFoundException
+ */
+ private function extractFileIdsFromTask(Task $task): array {
+ $ids = [];
+ $taskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
+ if (!isset($taskTypes[$task->getTaskTypeId()])) {
+ throw new \OCP\TaskProcessing\Exception\NotFoundException('Could not find task type');
+ }
+ $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)) {
+ /** @var int|list<int> $inputSlot */
+ $inputSlot = $task->getInput()[$key];
+ if (is_array($inputSlot)) {
+ $ids += $inputSlot;
+ } else {
+ $ids[] = $inputSlot;
+ }
+ }
+ }
+ 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)) {
+ /** @var int|list<int> $outputSlot */
+ $outputSlot = $task->getOutput()[$key];
+ if (is_array($outputSlot)) {
+ $ids += $outputSlot;
+ } else {
+ $ids[] = $outputSlot;
+ }
+ }
+ }
+ }
+ return array_values($ids);
+ }
+
+ /**
+ * This endpoint sets the task progress
+ *
+ * @param int $taskId The id of the task
+ * @param float $progress The progress
+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
+ *
+ * 200: File content returned
+ * 404: Task not found
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/tasks/{taskId}/progress', root: '/taskprocessing')]
+ public function setProgress(int $taskId, float $progress): DataResponse {
+ try {
+ $this->taskProcessingManager->setTaskProgress($taskId, $progress);
+ $task = $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+
+ /** @var CoreTaskProcessingTask $json */
+ $json = $task->jsonSerialize();
+
+ return new DataResponse([
+ 'task' => $json,
+ ]);
+ } catch (\OCP\TaskProcessing\Exception\NotFoundException $e) {
+ return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND);
+ } catch (Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This endpoint sets the task progress
+ *
+ * @param int $taskId The id of the task
+ * @param array<string,mixed>|null $output The resulting task output
+ * @param string|null $errorMessage An error message if the task failed
+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
+ *
+ * 200: File content returned
+ * 404: Task not found
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/tasks/{taskId}/result', root: '/taskprocessing')]
+ public function setResult(int $taskId, ?array $output = null, ?string $errorMessage = null): DataResponse {
+ try {
+ // Check if the current user can access the task
+ $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+ // set result
+ $this->taskProcessingManager->setTaskResult($taskId, $errorMessage, $output);
+ $task = $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+
+ /** @var CoreTaskProcessingTask $json */
+ $json = $task->jsonSerialize();
+
+ return new DataResponse([
+ 'task' => $json,
+ ]);
+ } catch (\OCP\TaskProcessing\Exception\NotFoundException $e) {
+ return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND);
+ } catch (Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This endpoint cancels a task
+ *
+ * @param int $taskId The id of the task
+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
+ *
+ * 200: File content returned
+ * 404: Task not found
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/tasks/{taskId}/cancel', root: '/taskprocessing')]
+ public function cancelTask(int $taskId): DataResponse {
+ try {
+ // Check if the current user can access the task
+ $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+ // set result
+ $this->taskProcessingManager->cancelTask($taskId);
+ $task = $this->taskProcessingManager->getUserTask($taskId, $this->userId);
+
+ /** @var CoreTaskProcessingTask $json */
+ $json = $task->jsonSerialize();
+
+ return new DataResponse([
+ 'task' => $json,
+ ]);
+ } catch (\OCP\TaskProcessing\Exception\NotFoundException $e) {
+ return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND);
+ } catch (Exception $e) {
+ return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+}
diff --git a/core/Migrations/Version30000Date20240429122720.php b/core/Migrations/Version30000Date20240429122720.php
new file mode 100644
index 00000000000..f4f16e07ada
--- /dev/null
+++ b/core/Migrations/Version30000Date20240429122720.php
@@ -0,0 +1,115 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2024 Marcel Klehr <mklehr@gmx.net>
+ *
+ * @author Marcel Klehr <mklehr@gmx.net>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Core\Migrations;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\DB\Types;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ *
+ */
+class Version30000Date20240429122720 extends SimpleMigrationStep {
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if (!$schema->hasTable('taskprocessing_tasks')) {
+ $table = $schema->createTable('taskprocessing_tasks');
+
+ $table->addColumn('id', Types::BIGINT, [
+ 'notnull' => true,
+ 'length' => 64,
+ 'autoincrement' => true,
+ ]);
+ $table->addColumn('type', Types::STRING, [
+ 'notnull' => true,
+ 'length' => 255,
+ ]);
+ $table->addColumn('input', Types::TEXT, [
+ 'notnull' => true,
+ ]);
+ $table->addColumn('output', Types::TEXT, [
+ 'notnull' => false,
+ ]);
+ $table->addColumn('status', Types::INTEGER, [
+ 'notnull' => false,
+ 'length' => 6,
+ 'default' => 0,
+ ]);
+ $table->addColumn('user_id', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 64,
+ ]);
+ $table->addColumn('app_id', Types::STRING, [
+ 'notnull' => true,
+ 'length' => 32,
+ 'default' => '',
+ ]);
+ $table->addColumn('custom_id', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 255,
+ 'default' => '',
+ ]);
+ $table->addColumn('last_updated', Types::INTEGER, [
+ 'notnull' => false,
+ 'length' => 4,
+ 'default' => 0,
+ 'unsigned' => true,
+ ]);
+ $table->addColumn('completion_expected_at', Types::DATETIME, [
+ 'notnull' => false,
+ ]);
+ $table->addColumn('progress', Types::FLOAT, [
+ 'notnull' => false,
+ 'default' => 0,
+ ]);
+ $table->addColumn('error_message', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 255,
+ ]);
+
+ $table->setPrimaryKey(['id'], 'taskp_tasks_id_index');
+ $table->addIndex(['status', 'type'], 'taskp_tasks_status_type');
+ $table->addIndex(['last_updated'], 'taskp_tasks_updated');
+ $table->addIndex(['user_id', 'app_id', 'custom_id'], 'taskp_tasks_uid_appid_cid');
+
+ return $schema;
+ }
+
+ return null;
+ }
+}
diff --git a/core/ResponseDefinitions.php b/core/ResponseDefinitions.php
index 4a79c3ad3ec..e0e8bed0044 100644
--- a/core/ResponseDefinitions.php
+++ b/core/ResponseDefinitions.php
@@ -176,6 +176,37 @@ namespace OCA\Core;
* iconURL: ?string,
* iconEmoji: ?string,
* }
+ *
+ * @psalm-type CoreTaskProcessingShape = array{
+ * name: string,
+ * description: string,
+ * type: "Number"|"Text"|"Audio"|"Image"|"Video"|"File"|"ListOfNumbers"|"ListOfTexts"|"ListOfImages"|"ListOfAudios"|"ListOfVideos"|"ListOfFiles",
+ * mandatory: bool,
+ * }
+ *
+ * @psalm-type CoreTaskProcessingTaskType = array{
+ * name: string,
+ * description: string,
+ * inputShape: CoreTaskProcessingShape[],
+ * outputShape: CoreTaskProcessingShape[],
+ * }
+ *
+ * @psalm-type CoreTaskProcessingIO = array<string, numeric|list<numeric>|string|list<string>>
+ *
+ * @psalm-type CoreTaskProcessingTask = array{
+ * id: int,
+ * lastUpdated: int,
+ * type: string,
+ * status: 'STATUS_CANCELLED'|'STATUS_FAILED'|'STATUS_SUCCESSFUL'|'STATUS_RUNNING'|'STATUS_SCHEDULED'|'STATUS_UNKNOWN',
+ * userId: ?string,
+ * appId: string,
+ * input: CoreTaskProcessingIO,
+ * output: null|CoreTaskProcessingIO,
+ * customId: ?string,
+ * completionExpectedAt: ?int,
+ * progress: ?float
+ * }
+ *
*/
class ResponseDefinitions {
}
diff --git a/core/openapi.json b/core/openapi.json
index 1c7b2caeeac..7563406dba0 100644
--- a/core/openapi.json
+++ b/core/openapi.json
@@ -466,6 +466,165 @@
}
}
},
+ "TaskProcessingIO": {
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "TaskProcessingShape": {
+ "type": "object",
+ "required": [
+ "name",
+ "description",
+ "type",
+ "mandatory"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "Number",
+ "Text",
+ "Audio",
+ "Image",
+ "Video",
+ "File",
+ "ListOfNumbers",
+ "ListOfTexts",
+ "ListOfImages",
+ "ListOfAudios",
+ "ListOfVideos",
+ "ListOfFiles"
+ ]
+ },
+ "mandatory": {
+ "type": "boolean"
+ }
+ }
+ },
+ "TaskProcessingTask": {
+ "type": "object",
+ "required": [
+ "id",
+ "lastUpdated",
+ "type",
+ "status",
+ "userId",
+ "appId",
+ "input",
+ "output",
+ "customId",
+ "completionExpectedAt",
+ "progress"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "lastUpdated": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "type": {
+ "type": "string"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "STATUS_CANCELLED",
+ "STATUS_FAILED",
+ "STATUS_SUCCESSFUL",
+ "STATUS_RUNNING",
+ "STATUS_SCHEDULED",
+ "STATUS_UNKNOWN"
+ ]
+ },
+ "userId": {
+ "type": "string",
+ "nullable": true
+ },
+ "appId": {
+ "type": "string"
+ },
+ "input": {
+ "$ref": "#/components/schemas/TaskProcessingIO"
+ },
+ "output": {
+ "$ref": "#/components/schemas/TaskProcessingIO",
+ "nullable": true
+ },
+ "customId": {
+ "type": "string",
+ "nullable": true
+ },
+ "completionExpectedAt": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true
+ },
+ "progress": {
+ "type": "number",
+ "format": "double",
+ "nullable": true
+ }
+ }
+ },
+ "TaskProcessingTaskType": {
+ "type": "object",
+ "required": [
+ "name",
+ "description",
+ "inputShape",
+ "outputShape"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "inputShape": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TaskProcessingShape"
+ }
+ },
+ "outputShape": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TaskProcessingShape"
+ }
+ }
+ }
+ },
"Team": {
"type": "object",
"required": [
@@ -3183,6 +3342,1487 @@
}
}
},
+ "/ocs/v2.php/taskprocessing/tasktypes": {
+ "get": {
+ "operationId": "task_processing_api-task-types",
+ "summary": "This endpoint returns all available TaskProcessing task types",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task types returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "types"
+ ],
+ "properties": {
+ "types": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/TaskProcessingTaskType"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/schedule": {
+ "post": {
+ "operationId": "task_processing_api-schedule",
+ "summary": "This endpoint allows scheduling a task",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "input",
+ "in": "query",
+ "description": "Task's input parameters",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "type",
+ "in": "query",
+ "description": "Type of the task",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "appId",
+ "in": "query",
+ "description": "ID of the app that will execute the task",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "customId",
+ "in": "query",
+ "description": "An arbitrary identifier for the task",
+ "schema": {
+ "type": "string",
+ "default": ""
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task scheduled successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "task"
+ ],
+ "properties": {
+ "task": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Scheduling task is not possible",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Scheduling task is not possible",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Cannot schedule task because it references files in its input that the user doesn't have access to",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/task/{id}": {
+ "get": {
+ "operationId": "task_processing_api-get-task",
+ "summary": "This endpoint allows checking the status and results of a task. Tasks are removed 1 week after receiving their last update",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "task"
+ ],
+ "properties": {
+ "task": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Task not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "task_processing_api-delete-task",
+ "summary": "This endpoint allows to delete a scheduled task for a user",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks/app/{appId}": {
+ "get": {
+ "operationId": "task_processing_api-list-tasks-by-app",
+ "summary": "This endpoint returns a list of tasks of a user that are related with a specific appId and optionally with an identifier",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "customId",
+ "in": "query",
+ "description": "An arbitrary identifier for the task",
+ "schema": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ {
+ "name": "appId",
+ "in": "path",
+ "description": "ID of the app",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task list returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "tasks"
+ ],
+ "properties": {
+ "tasks": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks": {
+ "get": {
+ "operationId": "task_processing_api-list-tasks-by-user",
+ "summary": "This endpoint returns a list of tasks of a user that are related with a specific appId and optionally with an identifier",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "taskType",
+ "in": "query",
+ "description": "The task type to filter by",
+ "schema": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ {
+ "name": "customId",
+ "in": "query",
+ "description": "An arbitrary identifier for the task",
+ "schema": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Task list returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "tasks"
+ ],
+ "properties": {
+ "tasks": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks/{taskId}/file/{fileId}": {
+ "get": {
+ "operationId": "task_processing_api-get-file-contents",
+ "summary": "This endpoint returns the contents of a file referenced in a task",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "taskId",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "fileId",
+ "in": "path",
+ "description": "The file id of the file to retrieve",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File content returned",
+ "content": {
+ "*/*": {
+ "schema": {
+ "type": "string",
+ "format": "binary"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Task or file not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks/{taskId}/progress": {
+ "post": {
+ "operationId": "task_processing_api-set-progress",
+ "summary": "This endpoint sets the task progress",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "progress",
+ "in": "query",
+ "description": "The progress",
+ "required": true,
+ "schema": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ {
+ "name": "taskId",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File content returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "task"
+ ],
+ "properties": {
+ "task": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Task not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks/{taskId}/result": {
+ "post": {
+ "operationId": "task_processing_api-set-result",
+ "summary": "This endpoint sets the task progress",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "output",
+ "in": "query",
+ "description": "The resulting task output",
+ "schema": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ {
+ "name": "errorMessage",
+ "in": "query",
+ "description": "An error message if the task failed",
+ "schema": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ {
+ "name": "taskId",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File content returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "task"
+ ],
+ "properties": {
+ "task": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Task not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/taskprocessing/tasks/{taskId}/cancel": {
+ "post": {
+ "operationId": "task_processing_api-cancel-task",
+ "summary": "This endpoint cancels a task",
+ "tags": [
+ "task_processing_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "taskId",
+ "in": "path",
+ "description": "The id of the task",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File content returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "task"
+ ],
+ "properties": {
+ "task": {
+ "$ref": "#/components/schemas/TaskProcessingTask"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Task not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/teams/{teamId}/resources": {
"get": {
"operationId": "teams_api-resolve-one",