diff --git a/lib/Controller/FileController.php b/lib/Controller/FileController.php index b480a30e9b..e1cccb3167 100644 --- a/lib/Controller/FileController.php +++ b/lib/Controller/FileController.php @@ -246,7 +246,8 @@ private function validate(?string $type = null, $identifier = null): DataRespons * List identification documents that need to be approved * * @param string|null $signer_uuid Signer UUID - * @param list|null $nodeIds The list of nodeIds (also called fileIds). It's the ids of files at Nextcloud + * @param list|null $fileIds The list of fileIds (database file IDs). It's the ids of LibreSign files + * @param list|null $nodeIds The list of nodeIds (also called fileIds). It's the ids of files at Nextcloud * @param list|null $status Status could be none or many of 0 = draft, 1 = able to sign, 2 = partial signed, 3 = signed, 4 = deleted. * @param int|null $page the number of page to return * @param int|null $length Total of elements to return @@ -266,6 +267,7 @@ public function list( ?int $page = null, ?int $length = null, ?string $signer_uuid = null, + ?array $fileIds = null, ?array $nodeIds = null, ?array $status = null, ?int $start = null, @@ -276,6 +278,7 @@ public function list( ): DataResponse { $filter = array_filter([ 'signer_uuid' => $signer_uuid, + 'fileIds' => $fileIds, 'nodeIds' => $nodeIds, 'status' => $status, 'start' => $start, @@ -355,6 +358,64 @@ public function getThumbnail( return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback); } + /** + * Return the thumbnail of a LibreSign file by fileId + * + * @param integer $fileId The LibreSign fileId (database id) + * @param integer $x Width of generated file + * @param integer $y Height of generated file + * @param boolean $a Crop, boolean value, default false + * @param boolean $forceIcon Force to generate a new thumbnail + * @param string $mode To force a given mimetype for the file + * @param boolean $mimeFallback If we have no preview enabled, we can redirect to the mime icon if any + * @return FileDisplayResponse|DataResponse, array{}>|RedirectResponse + * + * 200: OK + * 303: Redirect + * 400: Bad request + * 403: Forbidden + * 404: Not found + */ + #[NoAdminRequired] + #[NoCSRFRequired] + #[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/file/thumbnail/file_id/{fileId}', requirements: ['apiVersion' => '(v1)'])] + public function getThumbnailByFileId( + int $fileId = -1, + int $x = 32, + int $y = 32, + bool $a = false, + bool $forceIcon = true, + string $mode = 'fill', + bool $mimeFallback = false, + ) { + if ($fileId === -1 || $x === 0 || $y === 0) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); + } + + try { + $libreSignFile = $this->fileMapper->getById($fileId); + if ($libreSignFile->getUserId() !== $this->userSession->getUser()->getUID()) { + return new DataResponse([], Http::STATUS_FORBIDDEN); + } + + if ($libreSignFile->getNodeType() === 'envelope') { + if ($mimeFallback) { + $url = $this->mimeIconProvider->getMimeIconUrl('folder'); + if ($url) { + return new RedirectResponse($url); + } + } + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + $node = $this->accountService->getPdfByUuid($libreSignFile->getUuid()); + } catch (DoesNotExistException) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback); + } + /** * @return FileDisplayResponse|DataResponse, array{}>|RedirectResponse */ diff --git a/lib/Db/SignRequestMapper.php b/lib/Db/SignRequestMapper.php index 9380c2380c..f1586d7279 100644 --- a/lib/Db/SignRequestMapper.php +++ b/lib/Db/SignRequestMapper.php @@ -613,7 +613,15 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array } if (!empty($filter['nodeIds'])) { $qb->andWhere( - $qb->expr()->in('f.node_id', $qb->createNamedParameter($filter['nodeIds'], IQueryBuilder::PARAM_STR_ARRAY)) + $qb->expr()->orX( + $qb->expr()->in('f.node_id', $qb->createNamedParameter($filter['nodeIds'], IQueryBuilder::PARAM_INT_ARRAY)), + $qb->expr()->in('f.signed_node_id', $qb->createNamedParameter($filter['nodeIds'], IQueryBuilder::PARAM_INT_ARRAY)) + ) + ); + } + if (!empty($filter['fileIds'])) { + $qb->andWhere( + $qb->expr()->in('f.id', $qb->createNamedParameter($filter['fileIds'], IQueryBuilder::PARAM_INT_ARRAY)) ); } if (!empty($filter['status'])) { diff --git a/openapi-full.json b/openapi-full.json index 7e7453ff8a..eb067a38c4 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -4456,6 +4456,19 @@ "nullable": true } }, + { + "name": "fileIds[]", + "in": "query", + "description": "The list of fileIds (database file IDs). It's the ids of LibreSign files", + "schema": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + } + }, { "name": "nodeIds[]", "in": "query", @@ -4464,7 +4477,8 @@ "type": "array", "nullable": true, "items": { - "type": "string" + "type": "integer", + "format": "int64" } } }, @@ -4819,6 +4833,233 @@ } } }, + "/ocs/v2.php/apps/libresign/api/{apiVersion}/file/thumbnail/file_id/{fileId}": { + "get": { + "operationId": "file-get-thumbnail-by-file-id", + "summary": "Return the thumbnail of a LibreSign file by fileId", + "tags": [ + "file" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v1" + ], + "default": "v1" + } + }, + { + "name": "fileId", + "in": "path", + "description": "The LibreSign fileId (database id)", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "default": -1 + } + }, + { + "name": "x", + "in": "query", + "description": "Width of generated file", + "schema": { + "type": "integer", + "format": "int64", + "default": 32 + } + }, + { + "name": "y", + "in": "query", + "description": "Height of generated file", + "schema": { + "type": "integer", + "format": "int64", + "default": 32 + } + }, + { + "name": "a", + "in": "query", + "description": "Crop, boolean value, default false", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "forceIcon", + "in": "query", + "description": "Force to generate a new thumbnail", + "schema": { + "type": "integer", + "default": 1, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "mode", + "in": "query", + "description": "To force a given mimetype for the file", + "schema": { + "type": "string", + "default": "fill" + } + }, + { + "name": "mimeFallback", + "in": "query", + "description": "If we have no preview enabled, we can redirect to the mime icon if any", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "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": "OK", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "303": { + "description": "Redirect", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/ocs/v2.php/apps/libresign/api/{apiVersion}/file": { "post": { "operationId": "file-save", diff --git a/openapi.json b/openapi.json index 1cc8c82265..7d7c0a3b28 100644 --- a/openapi.json +++ b/openapi.json @@ -4306,6 +4306,19 @@ "nullable": true } }, + { + "name": "fileIds[]", + "in": "query", + "description": "The list of fileIds (database file IDs). It's the ids of LibreSign files", + "schema": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + } + }, { "name": "nodeIds[]", "in": "query", @@ -4314,7 +4327,8 @@ "type": "array", "nullable": true, "items": { - "type": "string" + "type": "integer", + "format": "int64" } } }, @@ -4669,6 +4683,233 @@ } } }, + "/ocs/v2.php/apps/libresign/api/{apiVersion}/file/thumbnail/file_id/{fileId}": { + "get": { + "operationId": "file-get-thumbnail-by-file-id", + "summary": "Return the thumbnail of a LibreSign file by fileId", + "tags": [ + "file" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v1" + ], + "default": "v1" + } + }, + { + "name": "fileId", + "in": "path", + "description": "The LibreSign fileId (database id)", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "default": -1 + } + }, + { + "name": "x", + "in": "query", + "description": "Width of generated file", + "schema": { + "type": "integer", + "format": "int64", + "default": 32 + } + }, + { + "name": "y", + "in": "query", + "description": "Height of generated file", + "schema": { + "type": "integer", + "format": "int64", + "default": 32 + } + }, + { + "name": "a", + "in": "query", + "description": "Crop, boolean value, default false", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "forceIcon", + "in": "query", + "description": "Force to generate a new thumbnail", + "schema": { + "type": "integer", + "default": 1, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "mode", + "in": "query", + "description": "To force a given mimetype for the file", + "schema": { + "type": "string", + "default": "fill" + } + }, + { + "name": "mimeFallback", + "in": "query", + "description": "If we have no preview enabled, we can redirect to the mime icon if any", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "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": "OK", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "303": { + "description": "Redirect", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/ocs/v2.php/apps/libresign/api/{apiVersion}/file": { "post": { "operationId": "file-save", diff --git a/src/Components/File/File.vue b/src/Components/File/File.vue index 87d8926c09..56565a7adc 100644 --- a/src/Components/File/File.vue +++ b/src/Components/File/File.vue @@ -3,7 +3,7 @@ - SPDX-License-Identifier: AGPL-3.0-or-later -->