From 0f519f4856fce91ec77b65b913a9b305271fb883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Fri, 13 Sep 2024 13:57:30 +0200 Subject: [PATCH] fix(files_external): broken credentials dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- apps/files_external/appinfo/routes.php | 5 -- .../lib/Controller/ApiController.php | 28 ------ .../src/actions/enterCredentialsAction.ts | 70 +++++++-------- .../src/views/CredentialsDialog.vue | 86 +++++++++++++++++++ 4 files changed, 119 insertions(+), 70 deletions(-) create mode 100644 apps/files_external/src/views/CredentialsDialog.vue diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php index b3f82cbad74e5..18418cc19c356 100644 --- a/apps/files_external/appinfo/routes.php +++ b/apps/files_external/appinfo/routes.php @@ -40,10 +40,5 @@ 'url' => '/api/v1/mounts', 'verb' => 'GET', ], - [ - 'name' => 'Api#askNativeAuth', - 'url' => '/api/v1/auth', - 'verb' => 'GET', - ], ], ]; diff --git a/apps/files_external/lib/Controller/ApiController.php b/apps/files_external/lib/Controller/ApiController.php index 5624293859339..10fd120c3d92f 100644 --- a/apps/files_external/lib/Controller/ApiController.php +++ b/apps/files_external/lib/Controller/ApiController.php @@ -15,7 +15,6 @@ use OCA\Files_External\Service\UserStoragesService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoAdminRequired; -use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\IRequest; @@ -103,31 +102,4 @@ public function getUserMounts(): DataResponse { return new DataResponse($entries); } - - /** - * Ask for credentials using a browser's native basic auth prompt - * Then returns it if provided - */ - #[NoAdminRequired] - #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] - public function askNativeAuth(): DataResponse { - if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) { - $response = new DataResponse([], Http::STATUS_UNAUTHORIZED); - $response->addHeader('WWW-Authenticate', 'Basic realm="Storage authentification needed"'); - return $response; - } - - $user = $_SERVER['PHP_AUTH_USER']; - $password = $_SERVER['PHP_AUTH_PW']; - - // Reset auth - unset($_SERVER['PHP_AUTH_USER']); - unset($_SERVER['PHP_AUTH_PW']); - - // Using 401 again to ensure we clear any cached Authorization - return new DataResponse([ - 'user' => $user, - 'password' => $password, - ], Http::STATUS_UNAUTHORIZED); - } } diff --git a/apps/files_external/src/actions/enterCredentialsAction.ts b/apps/files_external/src/actions/enterCredentialsAction.ts index 78377dc557ca8..29d660315b469 100644 --- a/apps/files_external/src/actions/enterCredentialsAction.ts +++ b/apps/files_external/src/actions/enterCredentialsAction.ts @@ -7,29 +7,39 @@ import type { AxiosResponse } from '@nextcloud/axios' import type { Node } from '@nextcloud/files' import type { StorageConfig } from '../services/externalStorage' -import { generateOcsUrl, generateUrl } from '@nextcloud/router' -import { showError, showSuccess } from '@nextcloud/dialogs' +import { generateUrl } from '@nextcloud/router' +import { showError, showSuccess, spawnDialog } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' import axios from '@nextcloud/axios' import LoginSvg from '@mdi/svg/svg/login.svg?raw' -import Vue from 'vue' +import Vue, { defineAsyncComponent } from 'vue' import { FileAction, DefaultType } from '@nextcloud/files' import { STORAGE_STATUS, isMissingAuthConfig } from '../utils/credentialsUtils' import { isNodeExternalStorage } from '../utils/externalStorageUtils' -type OCSAuthResponse = { - ocs: { - meta: { - status: string - statuscode: number - message: string - }, - data: { - user?: string, - password?: string, - } +type CredentialResponse = { + login?: string, + password?: string, +} + +async function setCredentials(node: Node, login: string, password: string): Promise { + const configResponse = await axios.put(generateUrl('apps/files_external/userglobalstorages/{id}', node.attributes), { + backendOptions: { user: login, password }, + }) as AxiosResponse + + const config = configResponse.data + if (config.status !== STORAGE_STATUS.SUCCESS) { + showError(t('files_external', 'Unable to update this external storage config. {statusMessage}', { + statusMessage: config?.statusMessage || '', + })) + return null } + + // Success update config attribute + showSuccess(t('files_external', 'New configuration successfully saved')) + Vue.set(node.attributes, 'config', config) + return true } export const action = new FileAction({ @@ -57,30 +67,16 @@ export const action = new FileAction({ }, async exec(node: Node) { - // always resolve auth request, we'll process the data afterwards - // Using fetch as axios have integrated auth handling and X-Requested-With header - const response = await fetch(generateOcsUrl('/apps/files_external/api/v1/auth'), { - headers: new Headers({ Accept: 'application/json' }), - credentials: 'include', - }) - - const data = (await response?.json() || {}) as OCSAuthResponse - if (data.ocs.data.user && data.ocs.data.password) { - const configResponse = await axios.put(generateUrl('apps/files_external/userglobalstorages/{id}', node.attributes), { - backendOptions: data.ocs.data, - }) as AxiosResponse - - const config = configResponse.data - if (config.status !== STORAGE_STATUS.SUCCESS) { - showError(t('files_external', 'Unable to update this external storage config. {statusMessage}', { - statusMessage: config?.statusMessage || '', - })) - return null - } + const { login, password } = await new Promise(resolve => spawnDialog( + defineAsyncComponent(() => import('../views/CredentialsDialog.vue')), + {}, + (args) => { + resolve(args as CredentialResponse) + }, + )) - // Success update config attribute - showSuccess(t('files_external', 'New configuration successfully saved')) - Vue.set(node.attributes, 'config', config) + if (login && password) { + return await setCredentials(node, login, password) } return null diff --git a/apps/files_external/src/views/CredentialsDialog.vue b/apps/files_external/src/views/CredentialsDialog.vue new file mode 100644 index 0000000000000..c9a9539f06164 --- /dev/null +++ b/apps/files_external/src/views/CredentialsDialog.vue @@ -0,0 +1,86 @@ + + + + +