mirror of
https://github.com/LibreSign/libresign.git
synced 2025-12-18 05:20:45 +01:00
Merge pull request #2424 from LibreSign/bugfix/thumbnail-for-guest
Generate thumbnail when is not my file
This commit is contained in:
commit
1af890de63
6 changed files with 165 additions and 18 deletions
|
|
@ -8,6 +8,7 @@ return [
|
|||
'ocs' => [
|
||||
['name' => 'File#save', 'url' => '/api/{apiVersion}/file', 'verb' => 'POST', 'requirements' => $requirements],
|
||||
['name' => 'File#list', 'url' => '/api/{apiVersion}/file/list', 'verb' => 'GET', 'requirements' => $requirements],
|
||||
['name' => 'File#getThumbnail', 'url' => '/api/{apiVersion}/file/thumbnail/{nodeId}', 'verb' => 'GET', 'requirements' => $requirements],
|
||||
['name' => 'File#validate', 'url' => '/api/{apiVersion}/file/validate/', 'verb' => 'GET', 'requirements' => $requirements],
|
||||
['name' => 'File#validateUuid', 'url' => '/api/{apiVersion}/file/validate/uuid/{uuid}', 'verb' => 'GET', 'requirements' => $requirements],
|
||||
['name' => 'File#validateFileId', 'url' => '/api/{apiVersion}/file/validate/file_id/{fileId}', 'verb' => 'GET', 'requirements' => $requirements],
|
||||
|
|
|
|||
|
|
@ -24,22 +24,35 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Libresign\Controller;
|
||||
|
||||
use OCA\Files_Sharing\SharedStorage;
|
||||
use OCA\Libresign\AppInfo\Application;
|
||||
use OCA\Libresign\Db\SignRequestMapper;
|
||||
use OCA\Libresign\Exception\LibresignException;
|
||||
use OCA\Libresign\Helper\JSActions;
|
||||
use OCA\Libresign\Helper\ValidateHelper;
|
||||
use OCA\Libresign\Middleware\Attribute\RequireManager;
|
||||
use OCA\Libresign\Service\FileService;
|
||||
use OCA\Libresign\Service\IdentifyMethodService;
|
||||
use OCA\Libresign\Service\SessionService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\Attribute\PublicPage;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IL10N;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Preview\IMimeIconProvider;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class FileController extends Controller {
|
||||
|
|
@ -49,6 +62,11 @@ class FileController extends Controller {
|
|||
private LoggerInterface $logger,
|
||||
private IUserSession $userSession,
|
||||
private SessionService $sessionService,
|
||||
private SignRequestMapper $signRequestMapper,
|
||||
private IdentifyMethodService $identifyMethodService,
|
||||
private IRootFolder $root,
|
||||
private IPreview $preview,
|
||||
private IMimeIconProvider $mimeIconProvider,
|
||||
private FileService $fileService,
|
||||
private ValidateHelper $validateHelper
|
||||
) {
|
||||
|
|
@ -142,6 +160,86 @@ class FileController extends Controller {
|
|||
return new JSONResponse($return, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
public function getThumbnail(
|
||||
int $nodeId = -1,
|
||||
int $x = 32,
|
||||
int $y = 32,
|
||||
bool $a = false,
|
||||
bool $forceIcon = true,
|
||||
string $mode = 'fill',
|
||||
bool $mimeFallback = false
|
||||
) {
|
||||
if ($nodeId === -1 || $x === 0 || $y === 0) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$myLibreSignFile = $this->fileService
|
||||
->setMe($this->userSession->getUser())
|
||||
->getMyLibresignFile($nodeId);
|
||||
} catch (DoesNotExistException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
$userFolder = $this->root->getUserFolder($myLibreSignFile->getUserId());
|
||||
$nodes = $userFolder->getById($nodeId);
|
||||
|
||||
$node = array_pop($nodes);
|
||||
|
||||
return $this->fetchPreview($node, $x, $y, $a, $forceIcon, $mode, $mimeFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
|
||||
*/
|
||||
private function fetchPreview(
|
||||
Node $node,
|
||||
int $x,
|
||||
int $y,
|
||||
bool $a,
|
||||
bool $forceIcon,
|
||||
string $mode,
|
||||
bool $mimeFallback = false,
|
||||
) : Http\Response {
|
||||
if (!($node instanceof File) || (!$forceIcon && !$this->preview->isAvailable($node))) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
if (!$node->isReadable()) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$storage = $node->getStorage();
|
||||
if ($storage->instanceOfStorage(SharedStorage::class)) {
|
||||
/** @var SharedStorage $storage */
|
||||
$share = $storage->getShare();
|
||||
$attributes = $share->getAttributes();
|
||||
if ($attributes !== null && $attributes->getAttribute('permissions', 'download') === false) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$f = $this->preview->getPreview($node, $x, $y, !$a, $mode);
|
||||
$response = new FileDisplayResponse($f, Http::STATUS_OK, [
|
||||
'Content-Type' => $f->getMimeType(),
|
||||
]);
|
||||
$response->cacheFor(3600 * 24, false, true);
|
||||
return $response;
|
||||
} catch (NotFoundException $e) {
|
||||
// If we have no preview enabled, we can redirect to the mime icon if any
|
||||
if ($mimeFallback) {
|
||||
if ($url = $this->mimeIconProvider->getMimeIconUrl($node->getMimeType())) {
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
}
|
||||
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[RequireManager]
|
||||
|
|
|
|||
|
|
@ -364,18 +364,25 @@ class SignRequestMapper extends QBMapper {
|
|||
return $return;
|
||||
}
|
||||
|
||||
private function getFilesAssociatedFilesWithMeStmt(string $userId, ?string $email): Pagination {
|
||||
public function getMyLibresignFile(string $userId, ?string $email, ?array $filter = []): File {
|
||||
$qb = $this->getFilesAssociatedFilesWithMeQueryBuilder(
|
||||
userId: $userId,
|
||||
email: $email,
|
||||
filter: $filter,
|
||||
);
|
||||
$qb->select('f.*');
|
||||
$cursor = $qb->executeQuery();
|
||||
$row = $cursor->fetch();
|
||||
if (!$row) {
|
||||
throw new DoesNotExistException('LibreSign file not found');
|
||||
}
|
||||
$file = new File();
|
||||
return $file->fromRow($row);
|
||||
}
|
||||
|
||||
private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, ?string $email, ?array $filter = []): IQueryBuilder {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(
|
||||
'f.id',
|
||||
'f.node_id',
|
||||
'f.user_id',
|
||||
'f.uuid',
|
||||
'f.name',
|
||||
'f.status'
|
||||
)
|
||||
->selectAlias('f.created_at', 'request_date')
|
||||
->from('libresign_file', 'f')
|
||||
$qb->from('libresign_file', 'f')
|
||||
->leftJoin('f', 'libresign_sign_request', 'sr', 'sr.file_id = f.id')
|
||||
->leftJoin('f', 'libresign_identify_method', 'im', $qb->expr()->eq('sr.id', 'im.sign_request_id'))
|
||||
->groupBy(
|
||||
|
|
@ -402,6 +409,27 @@ class SignRequestMapper extends QBMapper {
|
|||
);
|
||||
}
|
||||
$qb->where($qb->expr()->orX(...$or));
|
||||
if ($filter) {
|
||||
if (isset($filter['nodeId'])) {
|
||||
$qb->andWhere(
|
||||
$qb->expr()->eq('f.node_id', $qb->createNamedParameter($filter['nodeId'], IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
}
|
||||
}
|
||||
return $qb;
|
||||
}
|
||||
|
||||
private function getFilesAssociatedFilesWithMeStmt(string $userId, ?string $email, ?array $filter = []): Pagination {
|
||||
$qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($userId, $email, $filter);
|
||||
$qb->selectAlias('f.created_at', 'request_date');
|
||||
$qb->select(
|
||||
'f.id',
|
||||
'f.node_id',
|
||||
'f.user_id',
|
||||
'f.uuid',
|
||||
'f.name',
|
||||
'f.status'
|
||||
);
|
||||
|
||||
$countQueryBuilderModifier = function (IQueryBuilder &$qb): void {
|
||||
/** @todo improve this to don't do two queries */
|
||||
|
|
|
|||
|
|
@ -443,14 +443,15 @@ class FileService {
|
|||
*
|
||||
* @psalm-return array{data: array, pagination: array}
|
||||
*/
|
||||
public function listAssociatedFilesOfSignFlow($page = null, $length = null): array {
|
||||
public function listAssociatedFilesOfSignFlow($page = null, $length = null, array $filter = []): array {
|
||||
$page = $page ?? 1;
|
||||
$length = $length ?? (int) $this->appConfig->getAppValue('length_of_page', '100');
|
||||
|
||||
$data = $this->signRequestMapper->getFilesAssociatedFilesWithMeFormatted(
|
||||
$this->me,
|
||||
$page,
|
||||
$length
|
||||
$length,
|
||||
$filter,
|
||||
);
|
||||
$data['pagination']->setRootPath('/file/list');
|
||||
return [
|
||||
|
|
@ -458,4 +459,14 @@ class FileService {
|
|||
'pagination' => $data['pagination']->getPagination($page, $length)
|
||||
];
|
||||
}
|
||||
|
||||
public function getMyLibresignFile(int $nodeId): File {
|
||||
return $this->signRequestMapper->getMyLibresignFile(
|
||||
userId: $this->me->getUID(),
|
||||
email: $this->me->getEMailAddress(),
|
||||
filter: [
|
||||
'nodeId' => $nodeId,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<script>
|
||||
import FileIcon from 'vue-material-design-icons/File.vue'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { generateOcsUrl } from '@nextcloud/router'
|
||||
import { useFilesStore } from '../../store/files.js'
|
||||
|
||||
export default {
|
||||
|
|
@ -58,10 +58,10 @@ export default {
|
|||
return null
|
||||
}
|
||||
try {
|
||||
const previewUrl = generateUrl('/core/preview?fileId={fileid}', {
|
||||
fileid: this.currentNodeId,
|
||||
const previewUrl = generateOcsUrl('/apps/libresign/api/v1/file/thumbnail/{nodeId}', {
|
||||
nodeId: this.currentNodeId,
|
||||
})
|
||||
const url = new URL(window.location.origin + previewUrl)
|
||||
const url = new URL(previewUrl)
|
||||
|
||||
// Request tiny previews
|
||||
url.searchParams.set('x', this.gridMode ? '128' : '32')
|
||||
|
|
@ -70,7 +70,7 @@ export default {
|
|||
|
||||
// Handle cropping
|
||||
url.searchParams.set('a', this.cropPreviews === true ? '0' : '1')
|
||||
return url.href
|
||||
return url
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,15 @@
|
|||
<code>Base</code>
|
||||
</MissingDependency>
|
||||
</file>
|
||||
<file src="lib/Controller/FileController.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>SharedStorage</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedDocblockClass occurrences="2">
|
||||
<code>$share</code>
|
||||
<code>$storage</code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="lib/Controller/PageController.php">
|
||||
<InvalidThrow occurrences="1">
|
||||
<code>throw new NotLoggedInException();</code>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue