Skip to content

Commit 9832737

Browse files
authored
Merge pull request #47952 from nextcloud/backport/47945/stable28
[stable28] fix(files_external): broken credentials dialog
2 parents 264cd2d + 9310cc8 commit 9832737

7 files changed

Lines changed: 125 additions & 45 deletions

File tree

apps/files_external/appinfo/routes.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,5 @@
6262
'url' => '/api/v1/mounts',
6363
'verb' => 'GET',
6464
],
65-
[
66-
'name' => 'Api#askNativeAuth',
67-
'url' => '/api/v1/auth',
68-
'verb' => 'GET',
69-
],
7065
],
7166
];

apps/files_external/src/actions/enterCredentialsAction.ts

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,39 @@ import type { AxiosResponse } from 'axios'
2424
import type { Node } from '@nextcloud/files'
2525
import type { StorageConfig } from '../services/externalStorage'
2626

27-
import { generateOcsUrl, generateUrl } from '@nextcloud/router'
28-
import { showError, showSuccess } from '@nextcloud/dialogs'
27+
import { generateUrl } from '@nextcloud/router'
28+
import { showError, showSuccess, spawnDialog } from '@nextcloud/dialogs'
2929
import { translate as t } from '@nextcloud/l10n'
3030
import axios from '@nextcloud/axios'
3131
import LoginSvg from '@mdi/svg/svg/login.svg?raw'
32-
import Vue from 'vue'
32+
import Vue, { defineAsyncComponent } from 'vue'
3333

3434
import { FileAction, DefaultType } from '@nextcloud/files'
3535
import { STORAGE_STATUS, isMissingAuthConfig } from '../utils/credentialsUtils'
3636
import { isNodeExternalStorage } from '../utils/externalStorageUtils'
3737

38-
type OCSAuthResponse = {
39-
ocs: {
40-
meta: {
41-
status: string
42-
statuscode: number
43-
message: string
44-
},
45-
data: {
46-
user?: string,
47-
password?: string,
48-
}
38+
type CredentialResponse = {
39+
login?: string,
40+
password?: string,
41+
}
42+
43+
async function setCredentials(node: Node, login: string, password: string): Promise<null|true> {
44+
const configResponse = await axios.put(generateUrl('apps/files_external/userglobalstorages/{id}', node.attributes), {
45+
backendOptions: { user: login, password },
46+
}) as AxiosResponse<StorageConfig>
47+
48+
const config = configResponse.data
49+
if (config.status !== STORAGE_STATUS.SUCCESS) {
50+
showError(t('files_external', 'Unable to update this external storage config. {statusMessage}', {
51+
statusMessage: config?.statusMessage || '',
52+
}))
53+
return null
4954
}
55+
56+
// Success update config attribute
57+
showSuccess(t('files_external', 'New configuration successfully saved'))
58+
Vue.set(node.attributes, 'config', config)
59+
return true
5060
}
5161

5262
export const action = new FileAction({
@@ -74,30 +84,16 @@ export const action = new FileAction({
7484
},
7585

7686
async exec(node: Node) {
77-
// always resolve auth request, we'll process the data afterwards
78-
// Using fetch as axios have integrated auth handling and X-Requested-With header
79-
const response = await fetch(generateOcsUrl('/apps/files_external/api/v1/auth'), {
80-
headers: new Headers({ Accept: 'application/json' }),
81-
credentials: 'include',
82-
})
83-
84-
const data = (await response?.json() || {}) as OCSAuthResponse
85-
if (data.ocs.data.user && data.ocs.data.password) {
86-
const configResponse = await axios.put(generateUrl('apps/files_external/userglobalstorages/{id}', node.attributes), {
87-
backendOptions: data.ocs.data,
88-
}) as AxiosResponse<StorageConfig>
89-
90-
const config = configResponse.data
91-
if (config.status !== STORAGE_STATUS.SUCCESS) {
92-
showError(t('files_external', 'Unable to update this external storage config. {statusMessage}', {
93-
statusMessage: config?.statusMessage || '',
94-
}))
95-
return null
96-
}
87+
const { login, password } = await new Promise<CredentialResponse>(resolve => spawnDialog(
88+
defineAsyncComponent(() => import('../views/CredentialsDialog.vue')),
89+
{},
90+
(args) => {
91+
resolve(args as CredentialResponse)
92+
},
93+
))
9794

98-
// Success update config attribute
99-
showSuccess(t('files_external', 'New configuration successfully saved'))
100-
Vue.set(node.attributes, 'config', config)
95+
if (login && password) {
96+
return await setCredentials(node, login, password)
10197
}
10298

10399
return null
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<template>
7+
<NcDialog :buttons="dialogButtons"
8+
class="external-storage-auth"
9+
close-on-click-outside
10+
data-cy-external-storage-auth
11+
is-form
12+
:name="t('files_external', 'Storage credentials')"
13+
out-transition
14+
@submit="$emit('close', {login, password})"
15+
@update:open="$emit('close')">
16+
<!-- Header -->
17+
<NcNoteCard class="external-storage-auth__header"
18+
:text="t('files_external', 'To access the storage, you need to provide the authentification informations.')"
19+
type="info" />
20+
21+
<!-- Login -->
22+
<NcTextField ref="login"
23+
class="external-storage-auth__login"
24+
data-cy-external-storage-auth-dialog-login
25+
:label="t('files_external', 'Login')"
26+
:placeholder="t('files_external', 'Enter the storage login')"
27+
minlength="2"
28+
name="login"
29+
required
30+
:value.sync="login" />
31+
32+
<!-- Password -->
33+
<NcPasswordField ref="password"
34+
class="external-storage-auth__password"
35+
data-cy-external-storage-auth-dialog-password
36+
:label="t('files_external', 'Password')"
37+
:placeholder="t('files_external', 'Enter the storage password')"
38+
name="password"
39+
required
40+
:value.sync="password" />
41+
</NcDialog>
42+
</template>
43+
44+
<script lang="ts">
45+
import { defineComponent } from 'vue'
46+
import { t } from '@nextcloud/l10n'
47+
48+
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
49+
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
50+
import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js'
51+
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
52+
53+
export default defineComponent({
54+
name: 'CredentialsDialog',
55+
56+
components: {
57+
NcDialog,
58+
NcNoteCard,
59+
NcTextField,
60+
NcPasswordField,
61+
},
62+
63+
setup() {
64+
return {
65+
t,
66+
}
67+
},
68+
69+
data() {
70+
return {
71+
login: '',
72+
password: '',
73+
}
74+
},
75+
76+
computed: {
77+
dialogButtons() {
78+
return [{
79+
label: t('files_external', 'Submit'),
80+
type: 'primary',
81+
nativeType: 'submit',
82+
}]
83+
},
84+
},
85+
})
86+
</script>

dist/4076-4076.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/4076-4076.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)