Skip to content

Commit adfb905

Browse files
committed
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 <[email protected]>
1 parent 6ca8071 commit adfb905

File tree

6 files changed

+92
-1
lines changed

6 files changed

+92
-1
lines changed

css/admin.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ input#zoteroAPIKeyField {
2727
width: 300px;
2828
}
2929

30+
textarea#documentSigningCertField {
31+
width: 600px;
32+
}
33+
34+
textarea#documentSigningKeyField {
35+
width: 600px;
36+
}
37+
3038
textarea#documentSigningCaField {
3139
width: 600px;
3240
}

lib/Controller/SettingsController.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ public function updateWatermarkSettings($settings = []): JSONResponse {
237237
*/
238238
public function setPersonalSettings($templateFolder,
239239
$zoteroAPIKeyInput,
240+
$documentSigningCertInput,
241+
$documentSigningKeyInput,
240242
$documentSigningCaInput) {
241243
$message = $this->l10n->t('Saved');
242244
$status = 'success';
@@ -258,6 +260,22 @@ public function setPersonalSettings($templateFolder,
258260
}
259261
}
260262

263+
if ($documentSigningCertInput !== null) {
264+
try {
265+
$this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningCert', $documentSigningCertInput);
266+
} catch (PreConditionNotMetException $e) {
267+
$message = $this->l10n->t('Error when saving');
268+
$status = 'error';
269+
}
270+
}
271+
if ($documentSigningKeyInput !== null) {
272+
try {
273+
$this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningKey', $documentSigningKeyInput);
274+
} catch (PreConditionNotMetException $e) {
275+
$message = $this->l10n->t('Error when saving');
276+
$status = 'error';
277+
}
278+
}
261279
if ($documentSigningCaInput !== null) {
262280
try {
263281
$this->config->setUserValue($this->userId, 'richdocuments', 'documentSigningCa', $documentSigningCaInput);

lib/Controller/WopiController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ public function checkFileInfo(string $fileId, string $access_token): JSONRespons
167167
}
168168
$enableDocumentSigning = $this->config->getAppValue(Application::APPNAME, 'documentSigningEnabled', 'yes') === 'yes';
169169
if (!$isPublic && $enableDocumentSigning) {
170+
$documentSigningCert = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningCert', '');
171+
$response['UserPrivateInfo']['SignatureCert'] = $documentSigningCert;
172+
$documentSigningKey = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningKey', '');
173+
$response['UserPrivateInfo']['SignatureKey'] = $documentSigningKey;
170174
$documentSigningCa = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningCa', '');
171175
$response['UserPrivateInfo']['SignatureCa'] = $documentSigningCa;
172176
}

lib/Settings/Personal.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public function getForm() {
3535
[
3636
'templateFolder' => $this->config->getUserValue($this->userId, 'richdocuments', 'templateFolder', ''),
3737
'hasDocumentSigningSupport' => $this->capabilitiesService->hasDocumentSigningSupport(),
38+
'documentSigningCert' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningCert', ''),
39+
'documentSigningKey' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningKey', ''),
3840
'documentSigningCa' => $this->config->getUserValue($this->userId, 'richdocuments', 'documentSigningCa', ''),
3941
'hasZoteroSupport' => $this->capabilitiesService->hasZoteroSupport(),
4042
'zoteroAPIKey' => $this->config->getUserValue($this->userId, 'richdocuments', 'zoteroAPIKey', '')

src/personal.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ import { showError } from '@nextcloud/dialogs'
1717
this.zoteroAPIKeySaveButton = document.getElementById('zoteroAPIKeySave')
1818
this.zoteroAPIKeyRemoveButton = document.getElementById('zoteroAPIKeyRemove')
1919

20+
this.documentSigningCertInput = document.getElementById('documentSigningCertField')
21+
this.documentSigningCertSaveButton = document.getElementById('documentSigningCertSave')
22+
this.documentSigningCertRemoveButton = document.getElementById('documentSigningCertRemove')
23+
this.documentSigningKeyInput = document.getElementById('documentSigningKeyField')
24+
this.documentSigningKeySaveButton = document.getElementById('documentSigningKeySave')
25+
this.documentSigningKeyRemoveButton = document.getElementById('documentSigningKeyRemove')
2026
this.documentSigningCaInput = document.getElementById('documentSigningCaField')
2127
this.documentSigningCaSaveButton = document.getElementById('documentSigningCaSave')
2228
this.documentSigningCaRemoveButton = document.getElementById('documentSigningCaRemove')
@@ -36,10 +42,17 @@ import { showError } from '@nextcloud/dialogs'
3642

3743
this.zoteroAPIKeyRemoveButton.addEventListener('click', this.resetZoteroAPI.bind(this))
3844

45+
this.documentSigningCertSaveButton.addEventListener('click', function() {
46+
self.updateDocumentSigningCert(self.documentSigningCertInput.value)
47+
})
48+
this.documentSigningCertRemoveButton.addEventListener('click', this.resetDocumentSigningCert.bind(this))
49+
this.documentSigningKeySaveButton.addEventListener('click', function() {
50+
self.updateDocumentSigningKey(self.documentSigningKeyInput.value)
51+
})
52+
this.documentSigningKeyRemoveButton.addEventListener('click', this.resetDocumentSigningKey.bind(this))
3953
this.documentSigningCaSaveButton.addEventListener('click', function() {
4054
self.updateDocumentSigningCa(self.documentSigningCaInput.value)
4155
})
42-
4356
this.documentSigningCaRemoveButton.addEventListener('click', this.resetDocumentSigningCa.bind(this))
4457
}
4558

@@ -79,6 +92,42 @@ import { showError } from '@nextcloud/dialogs'
7992
})
8093
}
8194

95+
PersonalSettings.prototype.updateDocumentSigningCert = function(ca) {
96+
const self = this
97+
this._updateSetting({ documentSigningCertInput: ca }, function() {
98+
self.documentSigningCertInput.value = ca
99+
}, function() {
100+
showError(t('richdocuments', 'Failed to update the document signing CA chain'))
101+
})
102+
}
103+
104+
PersonalSettings.prototype.resetDocumentSigningCert = function() {
105+
const self = this
106+
this._updateSetting({ documentSigningCertInput: '' }, function() {
107+
self.documentSigningCertInput.value = ''
108+
}, function() {
109+
110+
})
111+
}
112+
113+
PersonalSettings.prototype.updateDocumentSigningKey = function(ca) {
114+
const self = this
115+
this._updateSetting({ documentSigningKeyInput: ca }, function() {
116+
self.documentSigningKeyInput.value = ca
117+
}, function() {
118+
showError(t('richdocuments', 'Failed to update the document signing CA chain'))
119+
})
120+
}
121+
122+
PersonalSettings.prototype.resetDocumentSigningKey = function() {
123+
const self = this
124+
this._updateSetting({ documentSigningKeyInput: '' }, function() {
125+
self.documentSigningKeyInput.value = ''
126+
}, function() {
127+
128+
})
129+
}
130+
82131
PersonalSettings.prototype.updateDocumentSigningCa = function(ca) {
83132
const self = this
84133
this._updateSetting({ documentSigningCaInput: ca }, function() {

templates/personal.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
<p><strong><?php p($l->t('Document signing')) ?></strong></p>
3434
<?php if ($_['hasDocumentSigningSupport']) { ?>
3535
<div class="input-wrapper">
36+
<p><label for="documentSigningCertField"><?php p($l->t('Enter document signing cert (in PEM format)')); ?></label><br />
37+
<textarea type="text" name="documentSigningCertField" id="documentSigningCertField"><?php p($_['documentSigningCert']); ?></textarea><br />
38+
<button id="documentSigningCertSave"><span title="<?php p($l->t('Save document signing cert')); ?>" data-toggle="tooltip">Save</span></button>
39+
<button id="documentSigningCertRemove"><span class="icon-delete" title="<?php p($l->t('Remove document signing cert')); ?>" data-toggle="tooltip"></span></button>
40+
</p>
41+
<p><label for="documentSigningKeyField"><?php p($l->t('Enter document signing key')); ?></label><br />
42+
<textarea type="text" name="documentSigningKeyField" id="documentSigningKeyField"><?php p($_['documentSigningKey']); ?></textarea><br />
43+
<button id="documentSigningKeySave"><span title="<?php p($l->t('Save document signing key')); ?>" data-toggle="tooltip">Save</span></button>
44+
<button id="documentSigningKeyRemove"><span class="icon-delete" title="<?php p($l->t('Remove document signing key')); ?>" data-toggle="tooltip"></span></button>
45+
</p>
3646
<p><label for="documentSigningCaField"><?php p($l->t('Enter document signing CA chain')); ?></label><br />
3747
<textarea type="text" name="documentSigningCaField" id="documentSigningCaField"><?php p($_['documentSigningCa']); ?></textarea><br />
3848
<button id="documentSigningCaSave"><span title="<?php p($l->t('Save document signing CA chain')); ?>" data-toggle="tooltip">Save</span></button>

0 commit comments

Comments
 (0)