From 76c8eeb5ed7774ef3389ed77d8b4c67ccc1d7478 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 10:05:41 -0300 Subject: [PATCH 01/21] Sign file by UUID --- appinfo/routes.php | 1 + lib/Controller/LibresignController.php | 48 ++++++++++++++++++++++++++ lib/Db/FileUserMapper.php | 16 +++++++++ 3 files changed, 65 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 047fe18fc..cf354732e 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -7,6 +7,7 @@ 'verb' => 'OPTIONS', 'requirements' => ['path' => '.+'], ], ['name' => 'webhook#register', 'url' => '/api/0.1/webhook/register', 'verb' => 'POST'], ['name' => 'libresign#sign', 'url' => '/api/0.1/sign', 'verb' => 'POST'], + ['name' => 'libresign#signUsingUuid', 'url' => '/api/0.1/sign/{uuid}', 'verb' => 'POST'], ['name' => 'account#createToSign', 'url' => '/api/0.1/account/create/{uuid}', 'verb' => 'POST'], ['name' => 'signature#generate', 'url' => '/api/0.1/signature/generate', 'verb' => 'POST'], ['name' => 'signature#hasRootCert', 'url' => '/api/0.1/signature/has-root-cert', 'verb' => 'GET'], diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index 8fe36bbdc..3c33e8da5 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -3,9 +3,15 @@ namespace OCA\Libresign\Controller; use OCA\Libresign\AppInfo\Application; +use OCA\Libresign\Db\FileMapper; +use OCA\Libresign\Db\FileUserMapper; +use OCA\Libresign\Helper\JSActions; use OCA\Libresign\Service\LibresignService; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\JSONResponse; +use OCP\Files\IRootFolder; use OCP\IRequest; class LibresignController extends Controller { @@ -15,16 +21,28 @@ class LibresignController extends Controller { /** @var LibresignService */ private $service; + /** @var FileUserMapper */ + private $fileUserMapper; + /** @var FileMapper */ + private $fileMapper; + /** @var IRootFolder */ + private $root; /** @var string */ private $userId; public function __construct( IRequest $request, LibresignService $service, + FileUserMapper $fileUserMapper, + FileMapper $fileMapper, + IRootFolder $root, $userId ) { parent::__construct(Application::APP_ID, $request); $this->service = $service; + $this->fileUserMapper = $fileUserMapper; + $this->fileMapper = $fileMapper; + $this->root = $root; $this->userId = $userId; } @@ -55,4 +73,34 @@ public function sign( return $this->handleErrors($exception); } } + + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function signUsingUuid($uuid) { + try { + $fileUser = $this->fileUserMapper->getByUuidAndUserId($uuid, $this->userId); + $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); + $filePreview = $this->root->getById($fileData->getFileId()); + if (count($filePreview) < 1) { + return new JSONResponse( + [ + 'message' => $this->l10n->t('File not found'), + 'action' => JSActions::ACTION_DO_NOTHING + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } + $filePreview = $filePreview[0]; + } catch (\Throwable $th) { + return new JSONResponse( + [ + 'action' => JSActions::ACTION_DO_NOTHING, + 'errors' => [$this->l10n->t('Invalid data to sign file')] + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } + } } diff --git a/lib/Db/FileUserMapper.php b/lib/Db/FileUserMapper.php index 15543573a..1b3ddbff0 100644 --- a/lib/Db/FileUserMapper.php +++ b/lib/Db/FileUserMapper.php @@ -53,4 +53,20 @@ public function getByUuid(string $uuid) { return $this->findEntity($qb); } + + public function getByUuidAndUserId(string $uuid, string $userId) { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from($this->getTableName()) + ->where( + $qb->expr()->eq('uuid', $qb->createNamedParameter($uuid, IQueryBuilder::PARAM_STR)) + ) + ->andWhere( + $qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)) + ); + + return $this->findEntity($qb); + } + } From 7dbfef5edb92ed298c370a9aa948f591053e8f1d Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 13:09:15 -0300 Subject: [PATCH 02/21] Compatibility to new constructor --- lib/Controller/LibresignController.php | 22 ++++++++++++--- .../Controller/LibresignControllerTest.php | 27 +++++++++++++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index 3c33e8da5..c74f94796 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -12,6 +12,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\JSONResponse; use OCP\Files\IRootFolder; +use OCP\IL10N; use OCP\IRequest; class LibresignController extends Controller { @@ -27,6 +28,8 @@ class LibresignController extends Controller { private $fileMapper; /** @var IRootFolder */ private $root; + /** @var IL10N */ + private $l10n; /** @var string */ private $userId; @@ -36,6 +39,7 @@ public function __construct( FileUserMapper $fileUserMapper, FileMapper $fileMapper, IRootFolder $root, + IL10N $l10n, $userId ) { parent::__construct(Application::APP_ID, $request); @@ -43,6 +47,7 @@ public function __construct( $this->fileUserMapper = $fileUserMapper; $this->fileMapper = $fileMapper; $this->root = $root; + $this->l10n = $l10n; $this->userId = $userId; } @@ -57,7 +62,7 @@ public function sign( string $outputFolderPath = null, string $certificatePath = null, string $password = null - ): DataResponse { + ): JSONResponse { try { $this->checkParams([ 'inputFilePath' => $inputFilePath, @@ -68,9 +73,18 @@ public function sign( $fileSigned = $this->service->sign($inputFilePath, $outputFolderPath, $certificatePath, $password); - return new DataResponse(['fileSigned' => $fileSigned->getInternalPath()]); + return new JSONResponse( + ['fileSigned' => $fileSigned->getInternalPath()], + HTTP::STATUS_OK + ); } catch (\Exception $exception) { - return $this->handleErrors($exception); + return new JSONResponse( + [ + 'action' => JSActions::ACTION_DO_NOTHING, + 'errors' => [$this->l10n->t($exception->getMessage())] + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); } } @@ -78,7 +92,7 @@ public function sign( * @NoAdminRequired * @NoCSRFRequired */ - public function signUsingUuid($uuid) { + public function signUsingUuid($uuid): JSONResponse { try { $fileUser = $this->fileUserMapper->getByUuidAndUserId($uuid, $this->userId); $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); diff --git a/tests/Unit/Controller/LibresignControllerTest.php b/tests/Unit/Controller/LibresignControllerTest.php index 224614734..fb37036b9 100644 --- a/tests/Unit/Controller/LibresignControllerTest.php +++ b/tests/Unit/Controller/LibresignControllerTest.php @@ -4,7 +4,11 @@ use OC\Files\Node\File; use OCA\Libresign\Controller\LibresignController; +use OCA\Libresign\Db\FileMapper; +use OCA\Libresign\Db\FileUserMapper; use OCA\Libresign\Service\LibresignService; +use OCP\Files\IRootFolder; +use OCP\IL10N; use OCP\IRequest; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; @@ -19,6 +23,10 @@ public function testSignFile() { $userId = 'john'; $request = $this->prophesize(IRequest::class); $service = $this->prophesize(LibresignService::class); + $fileUserMapper = $this->prophesize(FileUserMapper::class); + $fileMapper = $this->prophesize(FileMapper::class); + $root = $this->prophesize(IRootFolder::class); + $l10n = $this->prophesize(IL10N::class); $file = $this->prophesize(File::class); $file->getInternalPath()->willReturn("/path/to/someFileSigned"); @@ -35,6 +43,10 @@ public function testSignFile() { $controller = new LibresignController( $request->reveal(), $service->reveal(), + $fileUserMapper->reveal(), + $fileMapper->reveal(), + $root->reveal(), + $l10n->reveal(), $userId ); @@ -68,6 +80,13 @@ public function testSignFileFailParameterMissing( $userId = 'john'; $request = $this->prophesize(IRequest::class); $service = $this->prophesize(LibresignService::class); + $fileUserMapper = $this->prophesize(FileUserMapper::class); + $fileMapper = $this->prophesize(FileMapper::class); + $root = $this->prophesize(IRootFolder::class); + $l10n = $this->createMock(IL10N::class); + $l10n + ->method('t') + ->will($this->returnArgument(0)); $service->sign(\Prophecy\Argument::cetera()) ->shouldNotBeCalled(); @@ -75,12 +94,16 @@ public function testSignFileFailParameterMissing( $controller = new LibresignController( $request->reveal(), $service->reveal(), + $fileUserMapper->reveal(), + $fileMapper->reveal(), + $root->reveal(), + $l10n, $userId ); $result = $controller->sign($inputFilePath, $outputFolderPath, $certificatePath, $password); - static::assertSame(['message' => "parameter '{$paramenterMissing}' is required!"], $result->getData()); - static::assertSame(400, $result->getStatus()); + static::assertSame(["parameter '{$paramenterMissing}' is required!"], $result->getData()['errors']); + static::assertSame(422, $result->getStatus()); } } From 91c7fb22ed1314b6909a4902e0e23e828e604af1 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 13:22:07 -0300 Subject: [PATCH 03/21] Fix return base64 encoded --- lib/Controller/AccountController.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index ac70e9134..02242f9d2 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -76,16 +76,17 @@ public function createToSign(string $uuid, string $email, string $password, stri Http::STATUS_UNPROCESSABLE_ENTITY ); } - return new JSONResponse( - [ - 'message' => $this->l10n->t('Success'), - 'action' => JSActions::ACTION_SIGN, - 'pdf' => [ - 'base64' => $fileToSign->getContent() - ], - 'filename' => $fileData->getName(), - 'description' => $fileData->getDescription() + $data = [ + 'message' => $this->l10n->t('Success'), + 'action' => JSActions::ACTION_SIGN, + 'pdf' => [ + 'base64' => base64_encode($fileToSign->getContent()) ], + 'filename' => $fileData->getName(), + 'description' => $fileData->getDescription() + ]; + return new JSONResponse( + $data, Http::STATUS_OK ); } From c5e11096df9dbdf7c6fa5ade7ca7e614ba9bffc7 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 16:45:23 -0300 Subject: [PATCH 04/21] Convert endpoint createToSign to public --- lib/Controller/AccountController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index 02242f9d2..b58987c35 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -42,6 +42,7 @@ public function __construct( * @NoAdminRequired * @CORS * @NoCSRFRequired + * @PublicPage * @return JSONResponse */ public function createToSign(string $uuid, string $email, string $password, string $signPassword) { From ab1f34e3b9290bdca339ffaac2a50d8fe7322a06 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 16:46:40 -0300 Subject: [PATCH 05/21] Moved code to try-catch --- lib/Controller/AccountController.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index b58987c35..7ff8b5f1e 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -68,6 +68,15 @@ public function createToSign(string $uuid, string $email, string $password, stri ); } $fileToSign = $fileToSign[0]; + $data = [ + 'message' => $this->l10n->t('Success'), + 'action' => JSActions::ACTION_SIGN, + 'pdf' => [ + 'base64' => base64_encode($fileToSign->getContent()) + ], + 'filename' => $fileData->getName(), + 'description' => $fileData->getDescription() + ]; } catch (\Throwable $th) { return new JSONResponse( [ @@ -77,15 +86,6 @@ public function createToSign(string $uuid, string $email, string $password, stri Http::STATUS_UNPROCESSABLE_ENTITY ); } - $data = [ - 'message' => $this->l10n->t('Success'), - 'action' => JSActions::ACTION_SIGN, - 'pdf' => [ - 'base64' => base64_encode($fileToSign->getContent()) - ], - 'filename' => $fileData->getName(), - 'description' => $fileData->getDescription() - ]; return new JSONResponse( $data, Http::STATUS_OK From 2dc7250f8ac271e1d836a1a450bfc69f1da5b591 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 16:49:00 -0300 Subject: [PATCH 06/21] Move default name of signature file to property --- lib/Service/AccountService.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 5a94c45ef..1d08a03ac 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -32,6 +32,8 @@ class AccountService { private $newUserMail; /** @var CfsslHandler */ private $cfsslHandler; + /** @var string */ + private $pdfFilename = 'signature.pfx'; public function __construct( IL10N $l10n, @@ -127,17 +129,16 @@ public function createToSign($uuid, $uid, $password, $signPassword) { private function savePfx($uid, $content) { Filesystem::initMountPoints($uid); $folder = $this->folder->getFolderForUser(); - $filename = 'signature.pfx'; - if ($folder->nodeExists($filename)) { - $node = $folder->get($filename); + if ($folder->nodeExists($this->pdfFilename)) { + $node = $folder->get($this->pdfFilename); if (!$node instanceof File) { - throw new LibresignException("path {$filename} already exists and is not a file!", 400); + throw new LibresignException("path {$this->pdfFilename} already exists and is not a file!", 400); } $node->putContent($content); return $node; } - $file = $folder->newFile($filename); + $file = $folder->newFile($this->pdfFilename); $file->putContent($content); } } From 2a753f15cca65f3e80d6b6f08f1083ed71372cca Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 16:49:30 -0300 Subject: [PATCH 07/21] Method to get pfx file --- lib/Service/AccountService.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 1d08a03ac..89c04db84 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -141,4 +141,13 @@ private function savePfx($uid, $content) { $file = $folder->newFile($this->pdfFilename); $file->putContent($content); } + + public function getPfx($uid) { + Filesystem::initMountPoints($uid); + $folder = $this->folder->getFolderForUser(); + if (!$folder->nodeExists($this->pdfFilename)) { + throw new LibresignException("Signature file not found!", 400); + } + return $folder->get($this->pdfFilename); + } } From 21d6893c1212d0461a50537bfad9fe20006e9a80 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 16:51:23 -0300 Subject: [PATCH 08/21] Get data to sign file --- lib/Controller/LibresignController.php | 44 +++++++++++++++++++------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index c74f94796..dfc9138f5 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -5,7 +5,10 @@ use OCA\Libresign\AppInfo\Application; use OCA\Libresign\Db\FileMapper; use OCA\Libresign\Db\FileUserMapper; +use OCA\Libresign\Exception\LibresignException; +use OCA\Libresign\Handler\JLibresignHandler; use OCA\Libresign\Helper\JSActions; +use OCA\Libresign\Service\AccountService; use OCA\Libresign\Service\LibresignService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -30,6 +33,10 @@ class LibresignController extends Controller { private $root; /** @var IL10N */ private $l10n; + /** @var AccountService */ + private $account; + /** @var JLibresignHandler */ + private $libresignHandler; /** @var string */ private $userId; @@ -40,6 +47,8 @@ public function __construct( FileMapper $fileMapper, IRootFolder $root, IL10N $l10n, + AccountService $account, + JLibresignHandler $libresignHandler, $userId ) { parent::__construct(Application::APP_ID, $request); @@ -48,6 +57,8 @@ public function __construct( $this->fileMapper = $fileMapper; $this->root = $root; $this->l10n = $l10n; + $this->account = $account; + $this->libresignHandler = $libresignHandler; $this->userId = $userId; } @@ -92,21 +103,32 @@ public function sign( * @NoAdminRequired * @NoCSRFRequired */ - public function signUsingUuid($uuid): JSONResponse { + public function signUsingUuid(string $uuid, string $password): JSONResponse { try { $fileUser = $this->fileUserMapper->getByUuidAndUserId($uuid, $this->userId); $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); - $filePreview = $this->root->getById($fileData->getFileId()); - if (count($filePreview) < 1) { - return new JSONResponse( - [ - 'message' => $this->l10n->t('File not found'), - 'action' => JSActions::ACTION_DO_NOTHING - ], - Http::STATUS_UNPROCESSABLE_ENTITY - ); + $inputFile = $this->root->getById($fileData->getFileId()); + if (count($inputFile) < 1) { + throw new LibresignException($this->l10n->t('File not found')); } - $filePreview = $filePreview[0]; + $inputFile = $inputFile[0]; + $signedFilePath = preg_replace( + '/' . $inputFile->getExtension() . '$/', + $this->l10n->t('signed').'.'.$inputFile->getExtension(), + $inputFile->getPath() + ); + if ($this->root->nodeExists($signedFilePath)) { + $inputFile = $signedFilePath; + } + $certificatePath = $this->account->getPfx($fileUser->getUserId()); + list($filename, $content) = $this->libresignHandler->signExistingFile($inputFile, $certificatePath, $password); + return new JSONResponse( + [ + 'action' => JSActions::ACTION_DO_NOTHING, + 'message' => $this->l10n->t('File signed') + ], + Http::STATUS_OK + ); } catch (\Throwable $th) { return new JSONResponse( [ From 8b02901fada6e7ac6e36661e99d06d56ed1f7410 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 17:05:19 -0300 Subject: [PATCH 09/21] Fix test --- tests/Unit/Controller/LibresignControllerTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Unit/Controller/LibresignControllerTest.php b/tests/Unit/Controller/LibresignControllerTest.php index fb37036b9..353d07c4f 100644 --- a/tests/Unit/Controller/LibresignControllerTest.php +++ b/tests/Unit/Controller/LibresignControllerTest.php @@ -6,6 +6,8 @@ use OCA\Libresign\Controller\LibresignController; use OCA\Libresign\Db\FileMapper; use OCA\Libresign\Db\FileUserMapper; +use OCA\Libresign\Handler\JLibresignHandler; +use OCA\Libresign\Service\AccountService; use OCA\Libresign\Service\LibresignService; use OCP\Files\IRootFolder; use OCP\IL10N; @@ -27,6 +29,8 @@ public function testSignFile() { $fileMapper = $this->prophesize(FileMapper::class); $root = $this->prophesize(IRootFolder::class); $l10n = $this->prophesize(IL10N::class); + $accountService = $this->createMock(AccountService::class); + $libresignHandler = $this->createMock(JLibresignHandler::class); $file = $this->prophesize(File::class); $file->getInternalPath()->willReturn("/path/to/someFileSigned"); @@ -47,6 +51,8 @@ public function testSignFile() { $fileMapper->reveal(), $root->reveal(), $l10n->reveal(), + $accountService, + $libresignHandler, $userId ); From 4ff4bb11666469bea23738ee5b72ca273a5a7e0d Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 17:06:39 -0300 Subject: [PATCH 10/21] Fix tests --- tests/Unit/Controller/LibresignControllerTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Unit/Controller/LibresignControllerTest.php b/tests/Unit/Controller/LibresignControllerTest.php index 353d07c4f..a3a060b4f 100644 --- a/tests/Unit/Controller/LibresignControllerTest.php +++ b/tests/Unit/Controller/LibresignControllerTest.php @@ -93,6 +93,8 @@ public function testSignFileFailParameterMissing( $l10n ->method('t') ->will($this->returnArgument(0)); + $accountService = $this->createMock(AccountService::class); + $libresignHandler = $this->createMock(JLibresignHandler::class); $service->sign(\Prophecy\Argument::cetera()) ->shouldNotBeCalled(); @@ -104,6 +106,8 @@ public function testSignFileFailParameterMissing( $fileMapper->reveal(), $root->reveal(), $l10n, + $accountService, + $libresignHandler, $userId ); From 7826da755615fc54696057e3d75af138107ebd7a Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 17:54:35 -0300 Subject: [PATCH 11/21] Mount before access file --- lib/Controller/AccountController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index 7ff8b5f1e..7ab338a93 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -2,6 +2,7 @@ namespace OCA\Libresign\Controller; +use OC\Files\Filesystem; use OCA\Libresign\AppInfo\Application; use OCA\Libresign\Db\FileMapper; use OCA\Libresign\Db\FileUser; @@ -57,6 +58,7 @@ public function createToSign(string $uuid, string $email, string $password, stri $this->account->createToSign($uuid, $email, $password, $signPassword); $fileUser = $this->account->getFileUserByUuid($uuid); $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); + Filesystem::initMountPoints($fileData->getuserId()); $fileToSign = $this->root->getById($fileData->getFileId()); if (count($fileToSign) < 1) { return new JSONResponse( From eac85c1198cccf6458231d157816bc3150e9a110 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 17:56:16 -0300 Subject: [PATCH 12/21] Add required method --- lib/Db/File.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Db/File.php b/lib/Db/File.php index 3f6d4c26b..b8db60eee 100644 --- a/lib/Db/File.php +++ b/lib/Db/File.php @@ -11,6 +11,8 @@ * @method int getId() * @method void setFileId(int $fileId) * @method int getFileId() + * @method void setUserId(int $userId) + * @method int getUserId() * @method void setCreatedAt(string $createdAt) * @method string getCreatedAt() * @method void setDescription(string $description) From 6ce4fba5c13405507af9062219720f305df3f027 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 18:07:22 -0300 Subject: [PATCH 13/21] Remove unused property --- lib/Service/AccountService.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 89c04db84..4a2e6f798 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -22,8 +22,6 @@ class AccountService { private $fileUserMapper; /** @var IUserManager */ protected $userManager; - /** @var SignatureService */ - private $signature; /** @var FolderService */ private $folder; /** @var IConfig */ @@ -39,7 +37,6 @@ public function __construct( IL10N $l10n, FileUserMapper $fileUserMapper, IUserManager $userManager, - SignatureService $signature, FolderService $folder, IConfig $config, NewUserMailHelper $newUserMail, @@ -48,7 +45,6 @@ public function __construct( $this->l10n = $l10n; $this->fileUserMapper = $fileUserMapper; $this->userManager = $userManager; - $this->signature = $signature; $this->folder = $folder; $this->config = $config; $this->newUserMail = $newUserMail; From bd7e3be2864139a6d4e841bf239a1f7376d1dc8f Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 18:12:37 -0300 Subject: [PATCH 14/21] UserId is optional, not mandatory when create account --- lib/Service/FolderService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/FolderService.php b/lib/Service/FolderService.php index 0a6f728a1..6deff1b8a 100644 --- a/lib/Service/FolderService.php +++ b/lib/Service/FolderService.php @@ -20,7 +20,7 @@ public function __construct( IRootFolder $root, IConfig $config, IL10N $l10n, - string $userId + ?string $userId ) { $this->root = $root; $this->config = $config; From f3a345c70dc1521bd29479946e5109431878eefa Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 18:47:56 -0300 Subject: [PATCH 15/21] Mount storage before access file --- lib/Controller/LibresignController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index dfc9138f5..34d2c7526 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -2,6 +2,7 @@ namespace OCA\Libresign\Controller; +use OC\Files\Filesystem; use OCA\Libresign\AppInfo\Application; use OCA\Libresign\Db\FileMapper; use OCA\Libresign\Db\FileUserMapper; @@ -107,6 +108,7 @@ public function signUsingUuid(string $uuid, string $password): JSONResponse { try { $fileUser = $this->fileUserMapper->getByUuidAndUserId($uuid, $this->userId); $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); + Filesystem::initMountPoints($fileData->getuserId()); $inputFile = $this->root->getById($fileData->getFileId()); if (count($inputFile) < 1) { throw new LibresignException($this->l10n->t('File not found')); From cc0e53f326a4e5727e7f70ac546f64fce781e0b0 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 20:23:29 -0300 Subject: [PATCH 16/21] Update README with instructions to install JSignPDF --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index a025472eb..111dcc215 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,19 @@ Nextcloud app to sign PDF documents ## Setup +### Java and JSignPDF + +Add the follow to Nextcloud PHP container Dockerfile + +```Dockerfile +# Install Java and JsignPDF +RUN mkdir -p /usr/share/man/man1 +RUN apt-get install -y default-jre +RUN curl -OL https://sourceforge.net/projects/jsignpdf/files/stable/JSignPdf%201.6.4/JSignPdf-1.6.4.zip \ + && unzip JSignPdf-1.6.4.zip -d /opt \ + && rm JSignPdf-1.6.4.zip +``` + ### With CFSS server Up a cfssl server using this code: From 9dabb5d4e4ff3772bf244500d651e0741673bef3 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 20:24:01 -0300 Subject: [PATCH 17/21] Update JSignPDF integration to use installed binaries --- lib/Handler/JLibresignHandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Handler/JLibresignHandler.php b/lib/Handler/JLibresignHandler.php index ef220ac91..bb5c621a8 100644 --- a/lib/Handler/JLibresignHandler.php +++ b/lib/Handler/JLibresignHandler.php @@ -17,6 +17,8 @@ public function signExistingFile( ->setPdf($inputFile->getContent()) ->setPassword($password) ->setTempPath('/tmp/') + ->setIsUseJavaInstalled(true) + ->setjSignPdfJarPath('/opt/jsignpdf-1.6.4/JSignPdf.jar') ; $jSignPdf = new JSignPDF($param); From 55761473a945ade9dc6d3129540a3a881ffbc61f Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 20:24:57 -0300 Subject: [PATCH 18/21] Save signed PDF --- lib/Controller/LibresignController.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index 34d2c7526..8274c492c 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -120,10 +120,15 @@ public function signUsingUuid(string $uuid, string $password): JSONResponse { $inputFile->getPath() ); if ($this->root->nodeExists($signedFilePath)) { + $signedFile = $this->root->get($signedFilePath); $inputFile = $signedFilePath; } $certificatePath = $this->account->getPfx($fileUser->getUserId()); - list($filename, $content) = $this->libresignHandler->signExistingFile($inputFile, $certificatePath, $password); + list(, $signedContent) = $this->libresignHandler->signExistingFile($inputFile, $certificatePath, $password); + if (!$signedFile) { + $signedFile = $this->root->newFile($signedFilePath); + } + $signedFile->putContent($signedContent); return new JSONResponse( [ 'action' => JSActions::ACTION_DO_NOTHING, From 653956004e32d32a4fe9e82210de7b00ca50f545 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 20:30:19 -0300 Subject: [PATCH 19/21] Remove unused property --- tests/Unit/Service/AccountServiceTest.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/Unit/Service/AccountServiceTest.php b/tests/Unit/Service/AccountServiceTest.php index 6297b36c4..43fcfb87f 100644 --- a/tests/Unit/Service/AccountServiceTest.php +++ b/tests/Unit/Service/AccountServiceTest.php @@ -7,7 +7,6 @@ use OCA\Libresign\Handler\CfsslHandler; use OCA\Libresign\Service\AccountService; use OCA\Libresign\Service\FolderService; -use OCA\Libresign\Service\SignatureService; use OCA\Settings\Mailer\NewUserMailHelper; use OCP\IConfig; use OCP\IL10N; @@ -25,8 +24,6 @@ final class AccountServiceTest extends TestCase { private $fileUserMapper; /** @var IUserManager */ protected $userManager; - /** @var SignatureService */ - private $signatureService; /** @var FolderService */ private $folder; /** @var IConfig */ @@ -43,7 +40,6 @@ public function setUp(): void { ->will($this->returnArgument(0)); $this->fileUserMapper = $this->createMock(FileUserMapper::class); $this->userManager = $this->createMock(IUserManager::class); - $this->signature = $this->createMock(SignatureService::class); $this->folder = $this->createMock(FolderService::class); $this->config = $this->createMock(IConfig::class); $this->newUserMail = $this->createMock(NewUserMailHelper::class); @@ -52,7 +48,6 @@ public function setUp(): void { $this->l10n, $this->fileUserMapper, $this->userManager, - $this->signature, $this->folder, $this->config, $this->newUserMail, From 01c6f75d718d5264844166bacdaa6ce1d92f2bc5 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 22:26:19 -0300 Subject: [PATCH 20/21] Fix tests --- lib/Controller/AccountController.php | 2 +- .../Unit/Controller/AccountControllerTest.php | 34 ++-- tests/lib/user/dummy.php | 156 ++++++++++++++++++ 3 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 tests/lib/user/dummy.php diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index 7ab338a93..00ef65e3a 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -58,7 +58,7 @@ public function createToSign(string $uuid, string $email, string $password, stri $this->account->createToSign($uuid, $email, $password, $signPassword); $fileUser = $this->account->getFileUserByUuid($uuid); $fileData = $this->fileMapper->getById($fileUser->getLibresignFileId()); - Filesystem::initMountPoints($fileData->getuserId()); + Filesystem::initMountPoints($fileData->getUserId()); $fileToSign = $this->root->getById($fileData->getFileId()); if (count($fileToSign) < 1) { return new JSONResponse( diff --git a/tests/Unit/Controller/AccountControllerTest.php b/tests/Unit/Controller/AccountControllerTest.php index a070ba900..cf92cdd80 100644 --- a/tests/Unit/Controller/AccountControllerTest.php +++ b/tests/Unit/Controller/AccountControllerTest.php @@ -3,22 +3,23 @@ namespace OCA\Libresign\Tests\Unit\Controller; use OCA\Libresign\Controller\AccountController; -use OCA\Libresign\Db\File; +use OCA\Libresign\Db\File as LibresignFile; use OCA\Libresign\Db\FileMapper; use OCA\Libresign\Db\FileUser; -use OCA\Libresign\Db\FileUserMapper; use OCA\Libresign\Helper\JSActions; use OCA\Libresign\Service\AccountService; +use OCA\Libresign\Tests\lib\User\Dummy; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; -use OCP\Files\File as FileNode; +use OCP\Files\File; use OCP\Files\IRootFolder; -use OCP\Files\Node; use OCP\IL10N; use OCP\IRequest; use PHPUnit\Framework\TestCase; final class AccountControllerTest extends TestCase { + /** @var AccountController */ + private $controller; /** @var IRequest */ private $request; /** @var IL10N */ @@ -34,6 +35,9 @@ public function setUp(): void { parent::setUp(); $this->request = $this->createMock(IRequest::class); $this->l10n = $this->createMock(IL10N::class); + $this->l10n + ->method('t') + ->will($this->returnArgument(0)); $this->account = $this->createMock(AccountService::class); $this->fileMapper = $this->createMock(FileMapper::class); $this->root = $this->createMock(IRootFolder::class); @@ -47,9 +51,6 @@ public function setUp(): void { } public function testCreateSuccess() { - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); $fileUser = $this->createMock(FileUser::class); $fileUser ->method('__call') @@ -58,21 +59,34 @@ public function testCreateSuccess() { $this->account ->method('getFileUserByUuid') ->will($this->returnValue($fileUser)); - $fileData = $this->createMock(File::class); + + $fileData = $this->createMock(LibresignFile::class); $fileData ->method('__call') ->withConsecutive( + [$this->equalTo('getUserId'), $this->anything()], [$this->equalTo('getFileId'), $this->anything()], [$this->equalTo('getName'), $this->anything()] ) ->will($this->returnValueMap([ + ['getUserId', [], ''], ['getFileId', [], 1], ['getName', [], 'Filename'] ])); $this->fileMapper ->method('getById') ->will($this->returnValue($fileData)); - $node = $this->createMock(FileNode::class); + + $userDummyBackend = $this->createMock(Dummy::class); + $userDummyBackend + ->method('userExists') + ->will($this->returnValue(true)); + \OC::$server->getUserManager()->registerBackend($userDummyBackend); + \OC::$server->getSession()->set('user_id', 1); + + $node = $this->createMock(File::class); + $node->method('getContent') + ->will($this->returnvalue('PDF')); $this->root ->method('getById') ->will($this->returnValue([$node])); @@ -84,7 +98,7 @@ public function testCreateSuccess() { 'filename' => 'Filename', 'description' => null, 'pdf' => [ - 'base64' => null + 'base64' => 'UERG' ] ], Http::STATUS_OK); $this->assertEquals($expected, $actual); diff --git a/tests/lib/user/dummy.php b/tests/lib/user/dummy.php new file mode 100644 index 000000000..332639170 --- /dev/null +++ b/tests/lib/user/dummy.php @@ -0,0 +1,156 @@ +users[$uid])) { + return false; + } else { + $this->users[$uid] = $password; + return true; + } + } + + /** + * delete a user + * + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ + public function deleteUser($uid) { + if (isset($this->users[$uid])) { + unset($this->users[$uid]); + return true; + } else { + return false; + } + } + + /** + * Set password + * + * @param string $uid The username + * @param string $password The new password + * @return bool + * + * Change the password of a user + */ + public function setPassword($uid, $password) { + if (isset($this->users[$uid])) { + $this->users[$uid] = $password; + return true; + } else { + return false; + } + } + + /** + * Check if the password is correct + * + * @param string $uid The username + * @param string $password The password + * @return string|bool + * + * Check if the password is correct without logging in the user + * returns the user id or false + */ + public function checkPassword($uid, $password) { + if (isset($this->users[$uid]) && $this->users[$uid] === $password) { + return $uid; + } + + return false; + } + + public function loginName2UserName($loginName) { + if (isset($this->users[strtolower($loginName)])) { + return strtolower($loginName); + } + return false; + } + + /** + * Get a list of all users + * + * @param string $search + * @param null|int $limit + * @param null|int $offset + * @return string[] an array of all uids + */ + public function getUsers($search = '', $limit = null, $offset = null) { + if (empty($search)) { + return array_keys($this->users); + } + $result = []; + foreach (array_keys($this->users) as $user) { + if (stripos($user, $search) !== false) { + $result[] = $user; + } + } + return $result; + } + + /** + * check if a user exists + * + * @param string $uid the username + * @return boolean + */ + public function userExists($uid) { + return isset($this->users[$uid]); + } + + /** + * @return bool + */ + public function hasUserListings() { + return true; + } + + /** + * counts the users in the database + * + * @return int|bool + */ + public function countUsers() { + return 0; + } + + public function setDisplayName($uid, $displayName) { + $this->displayNames[$uid] = $displayName; + return true; + } + + public function getDisplayName($uid) { + return isset($this->displayNames[$uid])? $this->displayNames[$uid]: $uid; + } + + /** + * Backend name to be shown in user management + * @return string the name of the backend to be shown + */ + public function getBackendName() { + return 'Dummy'; + } +} From 08f95f5547b7f0ab9fe05ea7518024083d1d5378 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 14 Feb 2021 22:37:57 -0300 Subject: [PATCH 21/21] cs fix --- lib/Controller/AccountController.php | 1 - lib/Controller/LibresignController.php | 1 - lib/Db/FileUserMapper.php | 1 - 3 files changed, 3 deletions(-) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index 00ef65e3a..8545a3d12 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -5,7 +5,6 @@ use OC\Files\Filesystem; use OCA\Libresign\AppInfo\Application; use OCA\Libresign\Db\FileMapper; -use OCA\Libresign\Db\FileUser; use OCA\Libresign\Helper\JSActions; use OCA\Libresign\Service\AccountService; use OCP\AppFramework\ApiController; diff --git a/lib/Controller/LibresignController.php b/lib/Controller/LibresignController.php index 8274c492c..8ff6cb10c 100644 --- a/lib/Controller/LibresignController.php +++ b/lib/Controller/LibresignController.php @@ -13,7 +13,6 @@ use OCA\Libresign\Service\LibresignService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; -use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\JSONResponse; use OCP\Files\IRootFolder; use OCP\IL10N; diff --git a/lib/Db/FileUserMapper.php b/lib/Db/FileUserMapper.php index 1b3ddbff0..24f8d50f1 100644 --- a/lib/Db/FileUserMapper.php +++ b/lib/Db/FileUserMapper.php @@ -68,5 +68,4 @@ public function getByUuidAndUserId(string $uuid, string $userId) { return $this->findEntity($qb); } - }