libresign/lib/Controller/SignFileController.php
Vitor Mattos 45cd3c374d
chore: Add SPDX header
Signed-off-by: Vitor Mattos <vitor@php.rio>
2024-05-14 12:32:04 -03:00

213 lines
7.1 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Libresign\Controller;
use OCA\Libresign\AppInfo\Application;
use OCA\Libresign\Db\FileMapper;
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\CanSignRequestUuid;
use OCA\Libresign\Middleware\Attribute\RequireManager;
use OCA\Libresign\Middleware\Attribute\RequireSigner;
use OCA\Libresign\Service\FileService;
use OCA\Libresign\Service\IdentifyMethodService;
use OCA\Libresign\Service\SignFileService;
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\JSONResponse;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;
class SignFileController extends AEnvironmentAwareController implements ISignatureUuid {
use LibresignTrait;
public function __construct(
IRequest $request,
protected IL10N $l10n,
private SignRequestMapper $signRequestMapper,
private FileMapper $fileMapper,
protected IUserSession $userSession,
private ValidateHelper $validateHelper,
protected SignFileService $signFileService,
private IdentifyMethodService $identifyMethodService,
private FileService $fileService,
protected LoggerInterface $logger
) {
parent::__construct(Application::APP_ID, $request);
}
#[NoAdminRequired]
#[NoCSRFRequired]
#[RequireManager]
#[PublicPage]
public function signUsingFileId(int $fileId, string $method, array $elements = [], string $identifyValue = '', string $token = ''): JSONResponse {
return $this->sign($fileId, null, $method, $elements, $identifyValue, $token);
}
#[NoAdminRequired]
#[NoCSRFRequired]
#[RequireSigner]
#[PublicPage]
public function signUsingUuid(string $uuid, string $method, array $elements = [], string $identifyValue = '', string $token = ''): JSONResponse {
return $this->sign(null, $uuid, $method, $elements, $identifyValue, $token);
}
public function sign(int $fileId = null, string $signRequestUuid = null, string $method, array $elements = [], string $identifyValue = '', string $token = ''): JSONResponse {
try {
$user = $this->userSession->getUser();
$this->validateHelper->canSignWithIdentificationDocumentStatus(
$user,
$this->fileService->getIdentificationDocumentsStatus($user?->getUID())
);
$libreSignFile = $this->signFileService->getLibresignFile($fileId, $signRequestUuid);
$signRequest = $this->signFileService->getSignRequestToSign($libreSignFile, $signRequestUuid, $user);
$this->validateHelper->validateVisibleElementsRelation($elements, $signRequest, $user);
$this->validateHelper->validateCredentials($signRequest, $user, $method, $identifyValue, $token);
if ($method === 'password') {
$this->signFileService->setPassword($token);
} else {
$this->signFileService->setSignWithoutPassword(true);
}
$identifyMethod = $this->identifyMethodService->getIdentifiedMethod($signRequest->getId());
$this->signFileService
->setLibreSignFile($libreSignFile)
->setSignRequest($signRequest)
->setUserUniqueIdentifier($identifyMethod->getEntity()->getIdentifierValue())
->setFriendlyName($signRequest->getDisplayName())
->storeUserMetadata([
'user-agent' => $this->request->getHeader('User-Agent'),
'remote-address' => $this->request->getRemoteAddress(),
])
->setCurrentUser($user)
->setVisibleElements($elements)
->sign();
return new JSONResponse(
[
'action' => JSActions::ACTION_SIGNED,
'message' => $this->l10n->t('File signed'),
'file' => [
'uuid' => $libreSignFile->getUuid()
]
],
Http::STATUS_OK
);
} catch (LibresignException $e) {
return new JSONResponse(
[
'action' => JSActions::ACTION_DO_NOTHING,
'errors' => [$e->getMessage()]
],
Http::STATUS_UNPROCESSABLE_ENTITY
);
} catch (\Throwable $th) {
$message = $th->getMessage();
$action = JSActions::ACTION_DO_NOTHING;
switch ($message) {
case 'Password to sign not defined. Create a password to sign':
$action = JSActions::ACTION_CREATE_SIGNATURE_PASSWORD;
// no break
case 'Host violates local access rules.':
case 'Certificate Password Invalid.':
case 'Certificate Password is Empty.':
$message = $this->l10n->t($message);
break;
default:
$this->logger->error($message);
$this->logger->error(json_encode($th->getTrace()));
$message = $this->l10n->t('Internal error. Contact admin.');
}
}
return new JSONResponse(
[
'action' => $action,
'errors' => [$message]
],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
#[NoAdminRequired]
#[NoCSRFRequired]
#[PublicPage]
#[CanSignRequestUuid]
public function signRenew(string $method): JSONResponse {
$this->signFileService->renew(
$this->getSignRequestEntity(),
$method,
);
return new JSONResponse(
[
// TRANSLATORS Message sent to signer when the sign link was expired and was possible to request to renew. The signer will see this message on the screen and nothing more.
'message' => $this->l10n->t('Renewed with success. Access the link again.'),
]
);
}
#[NoAdminRequired]
#[NoCSRFRequired]
#[RequireSigner]
#[PublicPage]
public function getCodeUsingUuid(string $uuid): JSONResponse {
return $this->getCode($uuid);
}
#[NoAdminRequired]
#[NoCSRFRequired]
#[RequireSigner]
#[PublicPage]
public function getCodeUsingFileId(int $fileId): JSONResponse {
return $this->getCode(null, $fileId);
}
/**
* @todo validate if can request code
*/
private function getCode(string $uuid = null, int $fileId = null): JSONResponse {
try {
try {
if ($fileId) {
$signRequest = $this->signRequestMapper->getByFileIdAndUserId($fileId);
} else {
$signRequest = $this->signRequestMapper->getBySignerUuidAndUserId($uuid);
}
} catch (\Throwable $th) {
throw new LibresignException($this->l10n->t('Invalid data to sign file'), 1);
}
$libreSignFile = $this->fileMapper->getById($signRequest->getFileId());
$this->validateHelper->fileCanBeSigned($libreSignFile);
$this->signFileService->requestCode(
signRequest: $signRequest,
identifyMethodName: $this->request->getParam('identifyMethod', ''),
signMethodName: $this->request->getParam('signMethod', ''),
identify: $this->request->getParam('identify', ''),
);
$message = $this->l10n->t('The code to sign file was successfully requested.');
$statusCode = Http::STATUS_OK;
// } catch (\OCA\TwoFactorGateway\Exception\SmsTransmissionException $e) {
// // There was an error when to send SMS code to user.
// $message = $this->l10n->t('Failed to send code.');
// $statusCode = Http::STATUS_UNPROCESSABLE_ENTITY;
} catch (\Throwable $th) {
$message = $th->getMessage();
$statusCode = Http::STATUS_UNPROCESSABLE_ENTITY;
}
return new JSONResponse(
[
'message' => [$message],
],
$statusCode,
);
}
}