Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/richdocuments.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2022-03-25 18:48:46 +0300
committerJulius Härtl <jus@bitgrid.net>2022-04-06 18:54:00 +0300
commit8620100b19cc34f79e048c5b3312070381cdeadd (patch)
tree3622defcca09cd8152ac410fded2a44e5de09b97
parent522cb7bba6687b0b26d33b5c7453eebd909192ff (diff)
Add more helpful setup checksenh/setup-checks
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r--lib/Controller/SettingsController.php5
-rw-r--r--lib/Service/InitialStateService.php16
-rw-r--r--lib/Settings/Admin.php10
-rw-r--r--src/components/AdminSettings.vue111
-rw-r--r--src/components/SetupHints.vue89
-rw-r--r--src/helpers/setupcheck.js39
6 files changed, 203 insertions, 67 deletions
diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php
index 6107880b..9ba73e94 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -204,7 +204,10 @@ class SettingsController extends Controller{
$response = [
'status' => 'success',
- 'data' => ['message' => $message]
+ 'data' => [
+ 'discovery' => $this->wopiParser->getUrlSrc('application/vnd.oasis.opendocument.text')['urlsrc'],
+ 'message' => $message
+ ]
];
return new JSONResponse($response);
diff --git a/lib/Service/InitialStateService.php b/lib/Service/InitialStateService.php
index ff85ec4e..db28352c 100644
--- a/lib/Service/InitialStateService.php
+++ b/lib/Service/InitialStateService.php
@@ -27,6 +27,7 @@ namespace OCA\Richdocuments\Service;
use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Db\Wopi;
+use OCA\Richdocuments\WOPI\Parser;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
@@ -38,6 +39,9 @@ class InitialStateService {
/** @var CapabilitiesService */
private $capabilitiesService;
+ /** @var Parser */
+ private $parser;
+
/** @var IConfig */
private $config;
@@ -47,10 +51,12 @@ class InitialStateService {
public function __construct(
IInitialState $initialState,
CapabilitiesService $capabilitiesService,
+ Parser $parser,
IConfig $config
) {
$this->initialState = $initialState;
$this->capabilitiesService = $capabilitiesService;
+ $this->parser = $parser;
$this->config = $config;
}
@@ -82,4 +88,14 @@ class InitialStateService {
\OC::$server->getURLGenerator()->getAbsoluteURL(\OC::$server->getThemingDefaults()->getLogo())
: false));
}
+
+ public function provideSettings(): void {
+ $sampleBrowserUrl = null;
+ try {
+ $sampleBrowserUrl = $this->parser->getUrlSrc('application/vnd.oasis.opendocument.text')['urlsrc'] ?? null;
+ } catch (\Throwable $e) {
+ }
+ $this->initialState->provideInitialState('discovery', $sampleBrowserUrl);
+
+ }
}
diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php
index e67fe5f3..bc65547c 100644
--- a/lib/Settings/Admin.php
+++ b/lib/Settings/Admin.php
@@ -28,6 +28,8 @@ use OCA\Richdocuments\Service\CapabilitiesService;
use OCA\Richdocuments\Service\DemoService;
use OCA\Richdocuments\Service\InitialStateService;
use OCA\Richdocuments\TemplateManager;
+use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\Settings\ISettings;
@@ -70,7 +72,8 @@ class Admin implements ISettings {
public function getForm() {
$this->initialState->provideCapabilities();
- return new TemplateResponse(
+ $this->initialState->provideSettings();
+ $response = new TemplateResponse(
'richdocuments',
'admin',
[
@@ -94,6 +97,11 @@ class Admin implements ISettings {
],
'blank'
);
+ $csp = new EmptyContentSecurityPolicy();
+ // FIXME: This does not seem to get applied
+ $csp->addAllowedConnectDomain('*');
+ $response->setContentSecurityPolicy($csp);
+ return $response;
}
public function getSection() {
diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue
index 88eca9a9..5ac5a8ce 100644
--- a/src/components/AdminSettings.vue
+++ b/src/components/AdminSettings.vue
@@ -31,30 +31,10 @@
{{ t('richdocuments', 'Collabora Online is a powerful LibreOffice-based online office suite with collaborative editing, which supports all major documents, spreadsheet and presentation file formats and works together with all modern browsers.') }}
</p>
- <div v-if="settings.wopi_url && settings.wopi_url !== ''">
- <div v-if="serverError == 2 && isNginx && serverMode === 'builtin'" id="security-warning-state-failure">
- <span class="icon icon-close-white" /><span class="message">{{ t('richdocuments', 'Could not establish connection to the Collabora Online server. This might be due to a missing configuration of your web server. For more information, please visit: ') }}<a title="Connecting Collabora Online Single Click with Nginx"
- href="https://www.collaboraoffice.com/online/connecting-collabora-online-single-click-with-nginx/"
- target="_blank"
- rel="noopener"
- class="external">{{ t('richdocuments', 'Connecting Collabora Online Single Click with Nginx') }}</a></span>
- </div>
- <div v-else-if="serverError == 2" id="security-warning-state-failure">
- <span class="icon icon-close-white" /><span class="message">{{ t('richdocuments', 'Could not establish connection to the Collabora Online server.') }}</span>
- </div>
- <div v-else-if="serverError == 1" id="security-warning-state-failure">
- <span class="icon icon-loading" /><span class="message">{{ t('richdocuments', 'Setting up a new server') }}</span>
- </div>
- <div v-else-if="serverError == 3" id="security-warning-state-failure">
- <span class="icon icon-close-white" /><span class="message">{{ t('richdocuments', 'Collabora Online should use the same protocol as the server installation.') }}</span>
- </div>
- <div v-else id="security-warning-state-ok">
- <span class="icon icon-checkmark-white" /><span class="message">{{ t('richdocuments', 'Collabora Online server is reachable.') }}</span>
- </div>
- </div>
- <div v-else id="security-warning-state-warning">
- <span class="icon icon-error-white" /><span class="message">{{ t('richdocuments', 'Please configure a Collabora Online server to start editing documents') }}</span>
- </div>
+ <SetupHints :settings="settings"
+ :server-error="serverError"
+ :is-nginx="isNginx"
+ :server-mode="serverMode" />
<fieldset>
<div>
@@ -363,14 +343,13 @@ import SettingsExternalApps from './SettingsExternalApps'
import '@nextcloud/dialogs/styles/toast.scss'
-const SERVER_STATE_OK = 0
-const SERVER_STATE_LOADING = 1
-const SERVER_STATE_CONNECTION_ERROR = 2
-const PROTOCOL_MISMATCH = 3
+import SetupHints from './SetupHints'
+import { SETUP_HINTS, SERVER_MODE } from '../helpers/setupcheck'
export default {
name: 'AdminSettings',
components: {
+ SetupHints,
SettingsCheckbox,
SettingsInputText,
SettingsSelectTag,
@@ -391,7 +370,7 @@ export default {
hasNextcloudBranding: loadState('richdocuments', 'hasNextcloudBranding', true),
serverMode: '',
- serverError: Object.values(OC.getCapabilities().richdocuments.collabora).length > 0 ? SERVER_STATE_OK : SERVER_STATE_CONNECTION_ERROR,
+ serverError: SETUP_HINTS.SERVER_STATE_LOADING,
hostErrors: [window.location.host === 'localhost' || window.location.host === '127.0.0.1', window.location.protocol !== 'https:', false],
demoServers: null,
CODEInstalled: 'richdocumentscode' in OC.appswebroots,
@@ -433,7 +412,7 @@ export default {
return t('richdocuments', 'Contact {0} to get an own installation.', [this.settings.demoUrl.provider_name])
},
isSetup() {
- return this.serverError === SERVER_STATE_OK
+ return this.serverError === SETUP_HINTS.SERVER_STATE_OK
},
isOoxml() {
return this.settings.doc_format === 'ooxml'
@@ -442,16 +421,6 @@ export default {
return this.hostErrors.some(x => x)
},
},
- watch: {
- 'settings.wopi_url'(newVal, oldVal) {
- if (newVal !== oldVal) {
- const protocol = this.checkUrlProtocol(newVal)
- const nextcloudProtocol = this.checkUrlProtocol(window.location.href)
- if (protocol !== nextcloudProtocol) this.serverError = PROTOCOL_MISMATCH
- else this.serverError = Object.values(OC.getCapabilities().richdocuments.collabora).length > 0 ? SERVER_STATE_OK : SERVER_STATE_CONNECTION_ERROR
- }
- },
- },
beforeMount() {
for (const key in this.initial.settings) {
if (!Object.prototype.hasOwnProperty.call(this.initial.settings, key)) {
@@ -468,7 +437,7 @@ export default {
}
Vue.set(this.settings, 'data', this.initial.settings)
if (this.settings.wopi_url === '') {
- this.serverError = SERVER_STATE_CONNECTION_ERROR
+ this.serverError = SETUP_HINTS.SERVER_STATE_NOT_SETUP
}
Vue.set(this.settings, 'edit_groups', this.settings.edit_groups ? this.settings.edit_groups.split('|') : null)
Vue.set(this.settings, 'use_groups', this.settings.use_groups ? this.settings.use_groups.split('|') : null)
@@ -494,6 +463,7 @@ export default {
this.CODEAppID = 'richdocumentscode_arm64'
}
this.checkIfDemoServerIsActive()
+ this.setupCheck(this.initial.wopi_url, loadState('richdocuments', 'discovery', null))
},
methods: {
async fetchDemoServers() {
@@ -565,22 +535,50 @@ export default {
})
},
async updateServer() {
- this.serverError = SERVER_STATE_LOADING
+ this.serverError = SETUP_HINTS.SERVER_STATE_UPDATING
try {
- await this.updateSettings({
+ const { data } = await this.updateSettings({
wopi_url: this.settings.wopi_url,
disable_certificate_verification: this.settings.disable_certificate_verification,
})
- this.serverError = SERVER_STATE_OK
+ this.setupCheck(this.settings.wopi_url, data.data.discovery)
} catch (e) {
console.error(e)
- this.serverError = SERVER_STATE_CONNECTION_ERROR
+ this.serverError = SETUP_HINTS.SERVER_STATE_CONNECTION_ERROR
if (e.response.data.hint === 'missing_capabilities') {
+ this.serverError = SETUP_HINTS.SERVER_STATE_CONNECTION_ERROR_CAPABILITIES
showWarning('Could not connect to the /hosting/capabilities endpoint. Please check if your webserver configuration is up to date.')
}
}
this.checkIfDemoServerIsActive()
},
+ async setupCheck(wopiUrl, browserUrl) {
+ if (!wopiUrl) {
+ this.serverError = SETUP_HINTS.SERVER_STATE_NOT_SETUP
+ return
+ }
+ console.debug('setupCheck', wopiUrl, browserUrl)
+ // Validate that the Nextcloud server could obtain a proper url
+ if (!browserUrl) {
+ this.serverError = SETUP_HINTS.SERVER_STATE_CONNECTION_ERROR
+ return
+ }
+ // Check if discovery returns the proper protocol
+ if (browserUrl.slice(0, 5) !== (location.protocol + '//' + location.host).slice(0, 5)) {
+ this.serverError = SETUP_HINTS.PROTOCOL_MISMATCH
+ return
+ }
+
+ // Check browser reachability of Collabora Online
+ try {
+ await fetch(browserUrl, { mode: 'no-cors' })
+ } catch (e) {
+ this.serverError = SETUP_HINTS.SERVER_STATE_CLIENT_CONNECTION_ERROR
+ return
+ }
+
+ this.serverError = SETUP_HINTS.SERVER_STATE_OK
+ },
async updateSettings(data) {
this.updating = true
try {
@@ -607,13 +605,13 @@ export default {
this.settings.demoUrl = this.demoServers ? this.demoServers.find((server) => server.demo_url === this.settings.wopi_url) : null
this.settings.CODEUrl = this.CODEInstalled ? window.location.protocol + '//' + window.location.host + generateFilePath(this.CODEAppID, '', '') + 'proxy.php?req=' : null
if (this.settings.wopi_url && this.settings.wopi_url !== '') {
- this.serverMode = 'custom'
+ this.serverMode = SERVER_MODE.CUSTOM
}
if (this.settings.demoUrl) {
- this.serverMode = 'demo'
+ this.serverMode = SERVER_MODE.DEMO
this.approvedDemoModal = true
} else if (this.settings.CODEUrl && this.settings.CODEUrl === this.settings.wopi_url) {
- this.serverMode = 'builtin'
+ this.serverMode = SERVER_MODE.BUILTIN
}
},
demoServerLabel(server) {
@@ -629,16 +627,6 @@ export default {
this.settings.disable_certificate_verification = false
await this.updateServer()
},
- checkUrlProtocol(string) {
- let url
- try {
- url = new URL(string)
- } catch (_) {
- return false
- }
-
- return url.protocol
- },
},
}
</script>
@@ -672,13 +660,6 @@ export default {
border-bottom: 1px solid var(--color-border);
}
- #security-warning-state-failure,
- #security-warning-state-warning,
- #security-warning-state-ok {
- margin-top: 10px;
- margin-bottom: 20px;
- }
-
.option-inline {
margin-left: 25px;
&:not(.multiselect) {
diff --git a/src/components/SetupHints.vue b/src/components/SetupHints.vue
new file mode 100644
index 00000000..4cd85f36
--- /dev/null
+++ b/src/components/SetupHints.vue
@@ -0,0 +1,89 @@
+<template>
+ <div>
+ <div v-if="isState(SETUP_HINTS.SERVER_STATE_NOT_SETUP)" id="security-warning-state-warning">
+ <span class="icon icon-error-white" /><span class="message">{{ t('richdocuments', 'Please configure a Collabora Online server to start editing documents') }}</span>
+ </div>
+
+ <div v-else
+ :id="failureId">
+ <div v-if="isState(SETUP_HINTS.SERVER_STATE_LOADING)">
+ <span class="icon icon-loading" /><span class="message">{{ t('richdocuments', 'Checking the existing configuration') }}</span>
+ </div>
+
+ <div v-else-if="isState(SETUP_HINTS.SERVER_STATE_UPDATING)">
+ <span class="icon icon-loading" /><span class="message">{{ t('richdocuments', 'Setting new server URL and checking the configuration') }}</span>
+ </div>
+
+ <div v-else-if="isState(SETUP_HINTS.SERVER_STATE_CONNECTION_ERROR)">
+ <span class="icon icon-close-white" />
+ <span class="message">
+ {{ t('richdocuments', 'Could not establish connection to the Collabora Online server.') }}
+ <span v-if="isNginx && serverMode === SERVER_MODE.BUILTIN">
+ {{ t('richdocuments', 'This might be due to a missing configuration of your web server. For more information, please visit: ') }}
+ <a title="Connecting Collabora Online Single Click with Nginx" class="external">{{ t('richdocuments', 'Connecting Collabora Online Single Click with Nginx') }}</a></span>
+ </span>
+ </div>
+
+ <div v-else-if="isState(SETUP_HINTS.PROTOCOL_MISMATCH)">
+ <span class="icon icon-close-white" /><span class="message">{{ t('richdocuments', 'Collabora Online should use the same protocol as the server installation.') }}</span>
+ </div>
+ <div v-else-if="isState(SETUP_HINTS.SERVER_STATE_CLIENT_CONNECTION_ERROR)">
+ <span class="icon icon-close-white" /><span class="message">{{ t('richdocuments', 'Collabora Online is not reachable from the browser.') }}</span>
+ </div>
+
+ <div v-else>
+ <span class="icon icon-checkmark-white" /><span class="message">{{ t('richdocuments', 'Collabora Online server is reachable.') }}</span>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+
+import { SETUP_HINTS, SERVER_MODE } from '../helpers/setupcheck'
+
+export default {
+ name: 'SetupHints',
+ props: {
+ settings: {
+ type: Object,
+ },
+ serverError: {
+ type: Number,
+ },
+ serverMode: {
+ type: String,
+ },
+ isNginx: {
+ type: Boolean,
+ },
+ },
+ data() {
+ return {
+ SETUP_HINTS,
+ SERVER_MODE,
+ }
+ },
+ computed: {
+ isState() {
+ return (hint) => this.serverError === hint
+ },
+ failureId() {
+ if (this.isState(SETUP_HINTS.SERVER_STATE_OK)) {
+ return 'security-warning-state-ok'
+ }
+
+ return 'security-warning-state-failure'
+ },
+ },
+}
+</script>
+
+<style scoped>
+#security-warning-state-failure,
+#security-warning-state-warning,
+#security-warning-state-ok {
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+</style>
diff --git a/src/helpers/setupcheck.js b/src/helpers/setupcheck.js
new file mode 100644
index 00000000..4f2e5ff7
--- /dev/null
+++ b/src/helpers/setupcheck.js
@@ -0,0 +1,39 @@
+/*
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+export const SETUP_HINTS = {
+ SERVER_STATE_NOT_SETUP: -3,
+ SERVER_STATE_LOADING: -2,
+ SERVER_STATE_UPDATING: -1,
+ SERVER_STATE_OK: 0,
+
+ SERVER_STATE_CONNECTION_ERROR: 2,
+ SERVER_STATE_CLIENT_CONNECTION_ERROR: 3,
+ PROTOCOL_MISMATCH: 4,
+ SERVER_STATE_CONNECTION_ERROR_CAPABILITIES: 5,
+}
+
+export const SERVER_MODE = {
+ CUSTOM: 'custom',
+ BUILTIN: 'builtin',
+ DEMO: 'demo',
+}