From c3f1bb3e8399addf025f550dbbccb97844db661b Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 16 Oct 2024 09:15:21 +0200 Subject: [PATCH] feat: document signing, add setting for the signing certificate & key, too (fixes #4123) The CA chain for the document signing was already a user setting & it was exposed in the WOPI CheckFileInfo, but the actual signing certificate & key was missing, so signing was not possible. These are typically in a similar PEM format using just ASCII characters, so providing a textarea where the user can paste them sounds like a good fit. Add the read/write of this setting and also expose it as part of the private user info in WOPI CheckFileInfo. With this, once all 3 are configured, it's possible to sign a document in Nextcloud Office, using the Signature button on the Home tab of the notebookbar. Signed-off-by: Miklos Vajna (cherry picked from commit adfb9056d40af3a861463753f47e72ab5f2f905c) --- css/admin.scss | 8 +++++ lib/Controller/SettingsController.php | 18 ++++++++++ lib/Controller/WopiController.php | 4 +++ lib/Settings/Personal.php | 2 ++ src/personal.js | 51 ++++++++++++++++++++++++++- templates/personal.php | 10 ++++++ 6 files changed, 92 insertions(+), 1 deletion(-) diff --git a/css/admin.scss b/css/admin.scss index e3288991dd..19822c4112 100644 --- a/css/admin.scss +++ b/css/admin.scss @@ -27,6 +27,14 @@ input#zoteroAPIKeyField { width: 300px; } +textarea#documentSigningCertField { + width: 600px; +} + +textarea#documentSigningKeyField { + width: 600px; +} + textarea#documentSigningCaField { width: 600px; } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index e4af5ca6cd..cb72d91b85 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -236,6 +236,8 @@ public function updateWatermarkSettings($settings = []): JSONResponse { */ public function setPersonalSettings($templateFolder, $zoteroAPIKeyInput, + $documentSigningCertInput, + $documentSigningKeyInput, $documentSigningCaInput) { $message = $this->l10n->t('Saved'); $status = 'success'; @@ -257,6 +259,22 @@ public function setPersonalSettings($templateFolder, } } + if ($documentSigningCertInput !== null) { + try { + $this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningCert', $documentSigningCertInput); + } catch (PreConditionNotMetException $e) { + $message = $this->l10n->t('Error when saving'); + $status = 'error'; + } + } + if ($documentSigningKeyInput !== null) { + try { + $this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningKey', $documentSigningKeyInput); + } catch (PreConditionNotMetException $e) { + $message = $this->l10n->t('Error when saving'); + $status = 'error'; + } + } if ($documentSigningCaInput !== null) { try { $this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningCa', $documentSigningCaInput); diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php index a64f52cf6b..d93f16c91d 100644 --- a/lib/Controller/WopiController.php +++ b/lib/Controller/WopiController.php @@ -175,6 +175,10 @@ public function checkFileInfo($fileId, $access_token) { } $enableDocumentSigning = $this->config->getAppValue(Application::APPNAME, 'documentSigningEnabled', 'yes') === 'yes'; if (!$isPublic && $enableDocumentSigning) { + $documentSigningCert = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningCert', ''); + $response['UserPrivateInfo']['SignatureCert'] = $documentSigningCert; + $documentSigningKey = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningKey', ''); + $response['UserPrivateInfo']['SignatureKey'] = $documentSigningKey; $documentSigningCa = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningCa', ''); $response['UserPrivateInfo']['SignatureCa'] = $documentSigningCa; } diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index 352b89ab73..7a70aaa3cf 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -46,6 +46,8 @@ public function getForm() { [ 'templateFolder' => $this->config->getUserValue($this->userId, 'richdocuments', 'templateFolder', ''), 'hasDocumentSigningSupport' => $this->capabilitiesService->hasDocumentSigningSupport(), + 'documentSigningCert' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningCert', ''), + 'documentSigningKey' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningKey', ''), 'documentSigningCa' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningCa', ''), 'hasZoteroSupport' => $this->capabilitiesService->hasZoteroSupport(), 'zoteroAPIKey' => $this->config->getUserValue($this->userId, 'richdocuments', 'zoteroAPIKey', '') diff --git a/src/personal.js b/src/personal.js index 28e5bcaf16..e2e89a5c09 100644 --- a/src/personal.js +++ b/src/personal.js @@ -17,6 +17,12 @@ import { showError } from '@nextcloud/dialogs' this.zoteroAPIKeySaveButton = document.getElementById('zoteroAPIKeySave') this.zoteroAPIKeyRemoveButton = document.getElementById('zoteroAPIKeyRemove') + this.documentSigningCertInput = document.getElementById('documentSigningCertField') + this.documentSigningCertSaveButton = document.getElementById('documentSigningCertSave') + this.documentSigningCertRemoveButton = document.getElementById('documentSigningCertRemove') + this.documentSigningKeyInput = document.getElementById('documentSigningKeyField') + this.documentSigningKeySaveButton = document.getElementById('documentSigningKeySave') + this.documentSigningKeyRemoveButton = document.getElementById('documentSigningKeyRemove') this.documentSigningCaInput = document.getElementById('documentSigningCaField') this.documentSigningCaSaveButton = document.getElementById('documentSigningCaSave') this.documentSigningCaRemoveButton = document.getElementById('documentSigningCaRemove') @@ -36,10 +42,17 @@ import { showError } from '@nextcloud/dialogs' this.zoteroAPIKeyRemoveButton.addEventListener('click', this.resetZoteroAPI.bind(this)) + this.documentSigningCertSaveButton.addEventListener('click', function() { + self.updateDocumentSigningCert(self.documentSigningCertInput.value) + }) + this.documentSigningCertRemoveButton.addEventListener('click', this.resetDocumentSigningCert.bind(this)) + this.documentSigningKeySaveButton.addEventListener('click', function() { + self.updateDocumentSigningKey(self.documentSigningKeyInput.value) + }) + this.documentSigningKeyRemoveButton.addEventListener('click', this.resetDocumentSigningKey.bind(this)) this.documentSigningCaSaveButton.addEventListener('click', function() { self.updateDocumentSigningCa(self.documentSigningCaInput.value) }) - this.documentSigningCaRemoveButton.addEventListener('click', this.resetDocumentSigningCa.bind(this)) } @@ -79,6 +92,42 @@ import { showError } from '@nextcloud/dialogs' }) } + PersonalSettings.prototype.updateDocumentSigningCert = function(ca) { + const self = this + this._updateSetting({ documentSigningCertInput: ca }, function() { + self.documentSigningCertInput.value = ca + }, function() { + showError(t('richdocuments', 'Failed to update the document signing CA chain')) + }) + } + + PersonalSettings.prototype.resetDocumentSigningCert = function() { + const self = this + this._updateSetting({ documentSigningCertInput: '' }, function() { + self.documentSigningCertInput.value = '' + }, function() { + + }) + } + + PersonalSettings.prototype.updateDocumentSigningKey = function(ca) { + const self = this + this._updateSetting({ documentSigningKeyInput: ca }, function() { + self.documentSigningKeyInput.value = ca + }, function() { + showError(t('richdocuments', 'Failed to update the document signing CA chain')) + }) + } + + PersonalSettings.prototype.resetDocumentSigningKey = function() { + const self = this + this._updateSetting({ documentSigningKeyInput: '' }, function() { + self.documentSigningKeyInput.value = '' + }, function() { + + }) + } + PersonalSettings.prototype.updateDocumentSigningCa = function(ca) { const self = this this._updateSetting({ documentSigningCaInput: ca }, function() { diff --git a/templates/personal.php b/templates/personal.php index ac35a384e3..9cf81a4180 100644 --- a/templates/personal.php +++ b/templates/personal.php @@ -33,6 +33,16 @@

t('Document signing')) ?>

+


+
+ + +

+


+
+ + +