diff --git a/css/admin.scss b/css/admin.scss index 0d2a579709..19822c4112 100644 --- a/css/admin.scss +++ b/css/admin.scss @@ -27,6 +27,18 @@ input#zoteroAPIKeyField { width: 300px; } +textarea#documentSigningCertField { + width: 600px; +} + +textarea#documentSigningKeyField { + width: 600px; +} + +textarea#documentSigningCaField { + width: 600px; +} + #richdocuments, #richdocuments-templates { // inline buttons on section headers diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index d2eebe3a57..cb72d91b85 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -235,7 +235,10 @@ public function updateWatermarkSettings($settings = []): JSONResponse { * @return JSONResponse */ public function setPersonalSettings($templateFolder, - $zoteroAPIKeyInput) { + $zoteroAPIKeyInput, + $documentSigningCertInput, + $documentSigningKeyInput, + $documentSigningCaInput) { $message = $this->l10n->t('Saved'); $status = 'success'; @@ -256,6 +259,31 @@ 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); + } catch (PreConditionNotMetException $e) { + $message = $this->l10n->t('Error when saving'); + $status = 'error'; + } + } + $response = [ 'status' => $status, 'data' => ['message' => $message] diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php index a075a2bc83..d93f16c91d 100644 --- a/lib/Controller/WopiController.php +++ b/lib/Controller/WopiController.php @@ -173,6 +173,15 @@ public function checkFileInfo($fileId, $access_token) { $zoteroAPIKey = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'zoteroAPIKey', ''); $response['UserPrivateInfo']['ZoteroAPIKey'] = $zoteroAPIKey; } + $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; + } if ($wopi->hasTemplateId()) { $response['TemplateSource'] = $this->getWopiUrlForTemplate($wopi); } diff --git a/lib/Service/CapabilitiesService.php b/lib/Service/CapabilitiesService.php index e15cc7a660..a97c7a234b 100644 --- a/lib/Service/CapabilitiesService.php +++ b/lib/Service/CapabilitiesService.php @@ -85,6 +85,10 @@ public function hasWASMSupport(): bool { return $this->getCapabilities()['hasWASMSupport'] ?? false; } + public function hasDocumentSigningSupport(): bool { + return $this->getCapabilities()['hasDocumentSigningSupport'] ?? false; + } + public function hasFormFilling(): bool { return $this->isVersionAtLeast('24.04.5.2'); } diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index 03c544597c..7a70aaa3cf 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -45,6 +45,10 @@ public function getForm() { 'personal', [ '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 bbff0019ae..e2e89a5c09 100644 --- a/src/personal.js +++ b/src/personal.js @@ -17,6 +17,16 @@ 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') + const self = this this.templateSelectButton.addEventListener('click', function() { OC.dialogs.filepicker(t('richdocuments', 'Select a personal template folder'), function(datapath, returntype) { @@ -31,6 +41,19 @@ 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)) } PersonalSettings.prototype.updateSetting = function(path) { @@ -69,6 +92,60 @@ 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() { + self.documentSigningCaInput.value = ca + }, function() { + showError(t('richdocuments', 'Failed to update the document signing CA chain')) + }) + } + + PersonalSettings.prototype.resetDocumentSigningCa = function() { + const self = this + this._updateSetting({ documentSigningCaInput: '' }, function() { + self.documentSigningCaInput.value = '' + }, function() { + + }) + } + PersonalSettings.prototype._updateSetting = function(data, successCallback, errorCallback) { OC.msg.startAction('#documents-admin-msg', t('richdocuments', 'Saving …')) const request = new XMLHttpRequest() diff --git a/templates/personal.php b/templates/personal.php index b5e08ee81e..9cf81a4180 100644 --- a/templates/personal.php +++ b/templates/personal.php @@ -30,5 +30,28 @@

t('This instance does not support Zotero, because the feature is missing or disabled. Please contact the administration.')); ?>

+

t('Document signing')) ?>

+ +
+


+
+ + +

+


+
+ + +

+


+
+ + +

+

t('To use document signing, specify your signing certificate, key and CA chain here.')); ?>

+
+ +

t('This instance does not support document signing, because the feature is missing or disabled. Please contact the administrator.')); ?>

+