From ba22d477684894ce4b624ce811cec170b869a0b7 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Wed, 13 Nov 2024 08:52:44 -0300 Subject: [PATCH] feat: request to sign from files Signed-off-by: Vitor Mattos --- img/app-colored.svg | 1 + lib/AppInfo/Application.php | 5 + lib/Listener/LoadAdditionalListener.php | 45 ++++++ lib/Service/FolderService.php | 10 ++ package-lock.json | 194 ++++++++++------------- package.json | 1 + src/external.js | 6 +- src/init.js | 76 ++++++--- src/main.js | 6 +- tests/Unit/Service/FolderServiceTest.php | 1 + tests/psalm-baseline.xml | 15 ++ webpack.config.js | 1 + 12 files changed, 233 insertions(+), 128 deletions(-) create mode 100644 img/app-colored.svg create mode 100644 lib/Listener/LoadAdditionalListener.php diff --git a/img/app-colored.svg b/img/app-colored.svg new file mode 100644 index 000000000..57c0eeaf9 --- /dev/null +++ b/img/app-colored.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index f5dbfce01..5a64908f6 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -8,12 +8,14 @@ namespace OCA\Libresign\AppInfo; +use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files\Event\LoadSidebar; use OCA\Libresign\Activity\Listener as ActivityListener; use OCA\Libresign\Events\SendSignNotificationEvent; use OCA\Libresign\Events\SignedEvent; use OCA\Libresign\Files\TemplateLoader as FilesTemplateLoader; use OCA\Libresign\Listener\BeforeNodeDeletedListener; +use OCA\Libresign\Listener\LoadAdditionalListener; use OCA\Libresign\Listener\LoadSidebarListener; use OCA\Libresign\Listener\MailNotifyListener; use OCA\Libresign\Listener\NotificationListener; @@ -59,6 +61,9 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(BeforeNodeDeletedEvent::class, BeforeNodeDeletedListener::class); $context->registerEventListener(SignedEvent::class, SignedListener::class); + // Files newFile listener + $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class); + // Activity listeners $context->registerEventListener(SendSignNotificationEvent::class, ActivityListener::class); diff --git a/lib/Listener/LoadAdditionalListener.php b/lib/Listener/LoadAdditionalListener.php new file mode 100644 index 000000000..9bcee946a --- /dev/null +++ b/lib/Listener/LoadAdditionalListener.php @@ -0,0 +1,45 @@ + + */ +class LoadAdditionalListener implements IEventListener { + public function __construct( + private IAppManager $appManager, + private CertificateEngineHandler $certificateEngineHandler, + ) { + } + public function handle(Event $event): void { + if (!($event instanceof LoadAdditionalScriptsEvent)) { + return; + } + + if (!$this->appManager->isEnabledForUser('libresign')) { + return; + } + + if (!$this->certificateEngineHandler->getEngine()->isSetupOk()) { + return; + } + + if (class_exists('\OCA\Files\App')) { + Util::addInitScript(Application::APP_ID, 'libresign-init'); + } + } +} diff --git a/lib/Service/FolderService.php b/lib/Service/FolderService.php index 858dc165e..0b459ce3d 100644 --- a/lib/Service/FolderService.php +++ b/lib/Service/FolderService.php @@ -68,6 +68,16 @@ public function getFolder(): Folder { */ public function getFileById(?int $nodeId = null): File { if ($this->getUserId()) { + $mountsContainingFile = $this->userMountCache->getMountsForFileId($nodeId); + foreach ($mountsContainingFile as $fileInfo) { + $this->root->getByIdInPath($nodeId, $fileInfo->getMountPoint()); + } + $file = $this->root->getById($nodeId); + if ($file) { + /** @var File */ + return $file[0]; + } + $folder = $this->root->getUserFolder($this->getUserId()); $file = $folder->getById($nodeId); if ($file) { diff --git a/package-lock.json b/package-lock.json index 33530980c..eca8e95a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@nextcloud/password-confirmation": "^5.1.1", "@nextcloud/paths": "^2.2.1", "@nextcloud/router": "^3.0.1", + "@nextcloud/upload": "^1.7.0", "@nextcloud/vue": "^8.19.0", "blueimp-md5": "^2.19.0", "copy-webpack-plugin": "^12.0.2", @@ -2835,6 +2836,38 @@ "npm": "^10.0.0" } }, + "node_modules/@nextcloud/upload": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@nextcloud/upload/-/upload-1.7.0.tgz", + "integrity": "sha512-XJ44HXzqRhfgblcjC7M+3Pr52Cyl8NEUOzGckcVUx8JZl027aiKpkUdXE6yKseJDi7OsoBQzGzJiBXYTaPq3Rw==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@nextcloud/auth": "^2.4.0", + "@nextcloud/axios": "^2.5.1", + "@nextcloud/capabilities": "^1.2.0", + "@nextcloud/dialogs": "^6.0.1", + "@nextcloud/files": "^3.9.1", + "@nextcloud/l10n": "^3.1.0", + "@nextcloud/logger": "^3.0.2", + "@nextcloud/paths": "^2.2.1", + "@nextcloud/router": "^3.0.0", + "@nextcloud/sharing": "^0.2.3", + "axios": "^1.7.7", + "axios-retry": "^4.5.0", + "crypto-browserify": "^3.12.1", + "p-cancelable": "^4.0.1", + "p-queue": "^8.0.0", + "simple-eta": "^3.0.2" + }, + "engines": { + "node": "^20.0.0", + "npm": "^10.0.0" + }, + "peerDependencies": { + "@nextcloud/vue": "^8.0.0-beta || ^8.0.0", + "vue": "^2.7.16" + } + }, "node_modules/@nextcloud/vue": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.19.0.tgz", @@ -4782,9 +4815,7 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -4795,9 +4826,7 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/assert": { "version": "2.1.0", @@ -4857,6 +4886,18 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/axios-retry": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, "node_modules/babel-loader": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", @@ -5037,9 +5078,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.3", @@ -5142,9 +5181,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/brotli": { "version": "1.3.3", @@ -5159,9 +5196,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -5175,9 +5210,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", @@ -5188,9 +5221,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", @@ -5202,9 +5233,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^5.2.1", "randombytes": "^2.1.0", @@ -5218,9 +5247,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", - "dev": true, "license": "ISC", - "peer": true, "dependencies": { "bn.js": "^5.2.1", "browserify-rsa": "^4.1.0", @@ -5241,17 +5268,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/browserify-sign/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5266,17 +5289,13 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/browserify-sign/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -5285,9 +5304,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/browserify-zlib": { "version": "0.2.0", @@ -5369,9 +5386,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/builtin-modules": { "version": "3.3.0", @@ -5652,9 +5667,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -6090,9 +6103,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/cosmiconfig": { "version": "9.0.0", @@ -6146,9 +6157,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.5.3" @@ -6158,17 +6167,13 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -6181,9 +6186,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -6222,9 +6225,7 @@ "version": "3.12.1", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "browserify-cipher": "^1.0.1", "browserify-sign": "^4.2.3", @@ -6643,9 +6644,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -6704,9 +6703,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", @@ -6717,9 +6714,7 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -6876,9 +6871,7 @@ "version": "6.6.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -6893,9 +6886,7 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/emoji-mart-vue-fast": { "version": "15.0.3", @@ -8122,9 +8113,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -9044,9 +9033,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -9067,9 +9054,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -9186,9 +9171,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -9670,7 +9653,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "devOptional": true, "license": "ISC" }, "node_modules/ini": { @@ -10141,6 +10123,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", @@ -10767,9 +10761,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -11713,9 +11705,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" @@ -11728,9 +11718,7 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/mime": { "version": "1.6.0", @@ -11784,17 +11772,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/minimatch": { "version": "9.0.5", @@ -12397,6 +12381,15 @@ "license": "MIT", "peer": true }, + "node_modules/p-cancelable": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", + "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -12519,9 +12512,7 @@ "version": "5.1.7", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", - "dev": true, "license": "ISC", - "peer": true, "dependencies": { "asn1.js": "^4.10.1", "browserify-aes": "^1.2.0", @@ -12650,9 +12641,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -13148,9 +13137,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/property-information": { "version": "6.5.0", @@ -13206,9 +13193,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", @@ -13222,9 +13207,7 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", @@ -13312,9 +13295,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" @@ -13880,9 +13861,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -14375,9 +14354,7 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "license": "(MIT AND BSD-3-Clause)", - "peer": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -14497,6 +14474,12 @@ "license": "MIT", "optional": true }, + "node_modules/simple-eta": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/simple-eta/-/simple-eta-3.0.2.tgz", + "integrity": "sha512-+OmPgi01yHK/bRNQDoehUcV8fqs9nNJkG2DoWCnnLvj0lmowab7BH3v9776BG0y7dGEOLh0F7mfd37k+ht26Yw==", + "license": "MIT" + }, "node_modules/simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", @@ -16235,7 +16218,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "devOptional": true, "license": "MIT" }, "node_modules/utils-merge": { diff --git a/package.json b/package.json index 3b7c0be60..0679cadc7 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@nextcloud/password-confirmation": "^5.1.1", "@nextcloud/paths": "^2.2.1", "@nextcloud/router": "^3.0.1", + "@nextcloud/upload": "^1.7.0", "@nextcloud/vue": "^8.19.0", "blueimp-md5": "^2.19.0", "copy-webpack-plugin": "^12.0.2", diff --git a/src/external.js b/src/external.js index 51aab9089..1b36cfcdc 100644 --- a/src/external.js +++ b/src/external.js @@ -11,13 +11,17 @@ import { generateFilePath } from '@nextcloud/router' import App from './App.vue' -import './init.js' import './plugins/vuelidate.js' import router from './router/router.js' import store from './store/index.js' import './assets/styles/main.scss' +if (window.OCA && !window.OCA.LibreSign) { + Object.assign(window.OCA, { LibreSign: {} }) + console.debug('OCA.LibreSign initialized') +} + // CSP config for webpack dynamic chunk loading // eslint-disable-next-line __webpack_nonce__ = btoa(getRequestToken()) diff --git a/src/init.js b/src/init.js index e753a7b46..b34b27868 100644 --- a/src/init.js +++ b/src/init.js @@ -2,25 +2,61 @@ * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -// import store from './store' -// Init LibreSign -if (window.OCA && !window.OCA.LibreSign) { - Object.assign(window.OCA, { LibreSign: {} }) - console.debug('OCA.LibreSign initialized') -} +import Vue from 'vue' -// Enable NewFeature -window.OCA.LibreSign.enableFeature = (feature) => { - // store.dispatch('featureController/ENABLE_FEATURE', feature) -} -window.OCA.LibreSign.disableFeature = (feature) => { - // store.dispatch('featureController/DISABLE_FEATURE', feature) -} -window.OCA.LibreSign.getFeatures = () => { - // console.debug('Features: ', store.state.featureController.features) - // console.debug('Enabled Features: ', store.state.featureController.enabledFeatures) -} -window.OCA.LibreSign.setFeature = (feature) => { - // store.dispatch('featureController/SET_NEW_FEATURE', feature) -} +import axios from '@nextcloud/axios' +import { addNewFileMenuEntry, Permission } from '@nextcloud/files' +import { translate, translatePlural } from '@nextcloud/l10n' +import { generateOcsUrl } from '@nextcloud/router' +import { getUploader } from '@nextcloud/upload' + +import LibreSignLogoSvg from '../img/app-colored.svg?raw' +import logger from './logger.js' + +Vue.prototype.t = translate +Vue.prototype.n = translatePlural +Vue.prototype.OC = OC +Vue.prototype.OCA = OCA + +addNewFileMenuEntry({ + id: 'libresign-request', + displayName: t('libresign', 'New signature request'), + iconSvgInline: LibreSignLogoSvg, + uploadManager: getUploader(), + order: 1, + enabled() { + return Permission.CREATE !== 0 + }, + async handler(context, content) { + const input = document.createElement('input') + input.accept = 'application/pdf' + input.type = 'file' + input.onchange = async (ev) => { + const file = ev.target.files[0] + input.remove() + if (!file) { + return + } + + this.uploadManager.addNotifier(async (upload) => { + const path = context.path + '/' + upload.file.name + await axios.post(generateOcsUrl('/apps/libresign/api/v1/file'), { + file: { + path, + }, + name: upload.file.name, + }) + .then(async ({ data }) => { + await window.OCA.Files.Sidebar.open(path) + OCA.Files.Sidebar.setActiveTab('libresign') + }) + }) + this.uploadManager + .upload(file.name, file) + .catch((error) => logger.debug('Error while uploading', { error })) + } + + input.click() + }, +}) diff --git a/src/main.js b/src/main.js index 9c30fca6b..851139e9d 100644 --- a/src/main.js +++ b/src/main.js @@ -12,7 +12,6 @@ import { generateFilePath } from '@nextcloud/router' import App from './App.vue' -import './init.js' import './plugins/vuelidate.js' import router from './router/router.js' import store from './store/index.js' @@ -20,6 +19,11 @@ import store from './store/index.js' import './assets/styles/main.scss' import 'vue-advanced-cropper/dist/style.css' +if (window.OCA && !window.OCA.LibreSign) { + Object.assign(window.OCA, { LibreSign: {} }) + console.debug('OCA.LibreSign initialized') +} + // CSP config for webpack dynamic chunk loading // eslint-disable-next-line __webpack_nonce__ = btoa(getRequestToken()) diff --git a/tests/Unit/Service/FolderServiceTest.php b/tests/Unit/Service/FolderServiceTest.php index 1753cc494..d9669ae06 100644 --- a/tests/Unit/Service/FolderServiceTest.php +++ b/tests/Unit/Service/FolderServiceTest.php @@ -106,6 +106,7 @@ public function testGetFolderAsUnauthenticatedWhenUserIdIsInvalid():void { } public function testGetFileWithInvalidNodeId():void { + $this->userMountCache->method('getMountsForFileId')->wilLReturn([]); $folder = $this->createMock(\OCP\Files\Folder::class); $folder->method('isUpdateable')->willReturn(true); $this->root->method('getUserFolder')->willReturn($folder); diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 33a35a87d..2cffa019d 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -2,9 +2,13 @@ + + + + @@ -66,6 +70,17 @@ + + + + + + + + + + + diff --git a/webpack.config.js b/webpack.config.js index c00c2aa84..3b3a50251 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,6 +11,7 @@ const CopyPlugin = require('copy-webpack-plugin'); module.exports = merge(nextcloudWebpackConfig, { entry: { + init: path.resolve(path.join('src', 'init.js')), tab: path.resolve(path.join('src', 'tab.js')), settings: path.resolve(path.join('src', 'settings.js')), external: path.resolve(path.join('src', 'external.js')),