From a9fa62cc5232a20021f206d34f4d295129c72e2c Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 10 Dec 2024 08:45:19 +0100 Subject: [PATCH] feat: electronic signing, add settings for eIDEasy (fixes #4311) Electronic signing needs to store settings as richdocuments settings. This involves the API URL, a client ID visible to the browser and a secret, which is only used during server-side requests. The WOPI CheckFileInfo reply sends this information to the COOL server, similar to how it's done for digital signing (via PEM files). Add the settings as admin settings, otherwise normal users would be able to use eIDEasy services outside richdocuments. has instructions on what test data to use to try out the service in a test environment. Additionally, if the test CA is configured to be trusted as a user setting, then the green stamp icon will show up in the status bar. Signed-off-by: Miklos Vajna --- docs/app_settings.md | 6 ++++++ lib/Controller/SettingsController.php | 18 ++++++++++++++++++ lib/Controller/WopiController.php | 18 ++++++++++++++++++ lib/Settings/Admin.php | 3 +++ src/components/AdminSettings.vue | 24 ++++++++++++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/docs/app_settings.md b/docs/app_settings.md index d70426f08a..699effde41 100644 --- a/docs/app_settings.md +++ b/docs/app_settings.md @@ -24,3 +24,9 @@ token. These credentials then can be used by the 3rd party application to make c ### Canonical webroot Canonical webroot, in case there are multiple, for Collabora Online to use. Provide the one with least restrictions. E.g.: Use non-shibbolized webroot if this instance is accessed by both shibbolized and non-shibbolized webroots. You can ignore this setting if only one webroot is used to access this instance. + +### Electronic signature +From a shell running in the Nextcloud root directory, run the following `occ` +command to configure a non-default base URL for eID Easy. For example: + + ./occ config:app:set --value https://test.eideasy.com richdocuments esignature_base_url diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 0ae90da07a..6dee13062f 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -110,6 +110,9 @@ private function getSettingsData(): array { 'product_name' => $this->capabilitiesService->getServerProductName(), 'product_version' => $this->capabilitiesService->getProductVersion(), 'product_hash' => $this->capabilitiesService->getProductHash(), + 'esignature_base_url' => $this->appConfig->getAppValue('esignature_base_url'), + 'esignature_client_id' => $this->appConfig->getAppValue('esignature_client_id'), + 'esignature_secret' => $this->appConfig->getAppValue('esignature_secret'), ]; } @@ -122,6 +125,9 @@ public function setSettings( ?string $doc_format, ?string $external_apps, ?string $canonical_webroot, + ?string $esignature_base_url, + ?string $esignature_client_id, + ?string $esignature_secret, ): JSONResponse { if ($wopi_url !== null) { $this->appConfig->setAppValue('wopi_url', $wopi_url); @@ -158,6 +164,18 @@ public function setSettings( $this->appConfig->setAppValue('canonical_webroot', $canonical_webroot); } + if ($esignature_base_url !== null) { + $this->appConfig->setAppValue('esignature_base_url', $esignature_base_url); + } + + if ($esignature_client_id !== null) { + $this->appConfig->setAppValue('esignature_client_id', $esignature_client_id); + } + + if ($esignature_secret !== null) { + $this->appConfig->setAppValue('esignature_secret', $esignature_secret); + } + try { $output = new NullOutput(); $this->connectivityService->testDiscovery($output); diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php index cef78e99d5..12b635c12b 100644 --- a/lib/Controller/WopiController.php +++ b/lib/Controller/WopiController.php @@ -159,6 +159,7 @@ public function checkFileInfo(string $fileId, string $access_token): JSONRespons 'IsUserLocked' => $this->permissionManager->userIsFeatureLocked($wopi->getEditorUid()), 'EnableRemoteLinkPicker' => (bool)$wopi->getCanwrite() && !$isPublic && !$wopi->getDirect(), 'HasContentRange' => true, + 'ServerPrivateInfo' => [], ]; $enableZotero = $this->config->getAppValue(Application::APPNAME, 'zoteroEnabled', 'yes') === 'yes'; @@ -174,6 +175,23 @@ public function checkFileInfo(string $fileId, string $access_token): JSONRespons $response['UserPrivateInfo']['SignatureKey'] = $documentSigningKey; $documentSigningCa = $this->config->getUserValue($wopi->getEditorUid(), 'richdocuments', 'documentSigningCa', ''); $response['UserPrivateInfo']['SignatureCa'] = $documentSigningCa; + + $eSignatureBaseUrl = $this->config->getAppValue(Application::APPNAME, 'esignature_base_url'); + $eSignatureClientId = $this->config->getAppValue(Application::APPNAME, 'esignature_client_id'); + $eSignatureSecret = $this->config->getAppValue(Application::APPNAME, 'esignature_secret'); + if ($eSignatureBaseUrl === '' && $eSignatureClientId !== '' && $eSignatureSecret !== '') { + // If the client ID & secret is set, then assume a production base URL. + $eSignatureBaseUrl = 'https://id.eideasy.com'; + } + if ($eSignatureBaseUrl !== '') { + $response['ServerPrivateInfo']['ESignatureBaseUrl'] = $eSignatureBaseUrl; + } + if ($eSignatureClientId !== '') { + $response['ServerPrivateInfo']['ESignatureClientId'] = $eSignatureClientId; + } + if ($eSignatureSecret !== '') { + $response['ServerPrivateInfo']['ESignatureSecret'] = $eSignatureSecret; + } } if ($wopi->hasTemplateId()) { $response['TemplateSource'] = $this->getWopiUrlForTemplate($wopi); diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index a5e9778923..7dc7158bb6 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -53,6 +53,9 @@ public function getForm(): TemplateResponse { 'os_family' => PHP_VERSION_ID >= 70200 ? PHP_OS_FAMILY : PHP_OS, 'platform' => php_uname('m'), 'fonts' => $this->fontService->getFontFileNames(), + 'esignature_base_url' => $this->config->getAppValue('richdocuments', 'esignature_base_url'), + 'esignature_client_id' => $this->config->getAppValue('richdocuments', 'esignature_client_id'), + 'esignature_secret' => $this->config->getAppValue('richdocuments', 'esignature_secret'), ], ], 'blank' diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue index d701bd6466..a9c4678cf2 100644 --- a/src/components/AdminSettings.vue +++ b/src/components/AdminSettings.vue @@ -391,6 +391,20 @@ +
+

{{ t('richdocuments', 'Electronic signature settings') }}

+ + +
+ @@ -688,6 +702,16 @@ export default { wopi_allowlist: allowlist, }) }, + async updateESignatureClientId(id) { + await this.updateSettings({ + esignature_client_id: id, + }) + }, + async updateESignatureSecret(secret) { + await this.updateSettings({ + esignature_secret: secret, + }) + }, async updateOoxml(enabled) { this.settings.doc_format = enabled ? 'ooxml' : '' await this.updateSettings({