fix(core): prompt for password once when installing recommended apps

Wire the password-confirmation interceptors into the recommendedapps
entry point and switch the installer to a single bulk enable call so
the strict password confirmation on enableApps is satisfied.

Fixes #60068
-e
Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
This commit is contained in:
Peter Ringelmann 2026-05-05 14:30:01 +02:00 committed by Peter R.
parent 9cdb6d1d17
commit d00d2b907b
11 changed files with 85 additions and 39 deletions

View file

@ -57,9 +57,9 @@
<script>
import { t } from '@nextcloud/l10n'
import { loadState } from '@nextcloud/initial-state'
import { PwdConfirmationMode } from '@nextcloud/password-confirmation'
import { generateUrl, imagePath } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import pLimit from 'p-limit'
import logger from '../../logger.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
@ -139,35 +139,41 @@ export default {
}
},
methods: {
installApps() {
this.installingApps = true
const limit = pLimit(1)
const installing = this.recommendedApps
async installApps() {
const apps = this.recommendedApps
.filter(app => !app.active && app.isCompatible && app.canInstall && app.isSelected)
.map(app => limit(async () => {
logger.info(`installing ${app.id}`)
app.loading = true
return axios.post(generateUrl('settings/apps/enable'), { appIds: [app.id], groups: [] })
.catch(error => {
logger.error(`could not install ${app.id}`, { error })
app.isSelected = false
app.installationError = true
})
.then(() => {
logger.info(`installed ${app.id}`)
app.loading = false
app.active = true
})
}))
logger.debug(`installing ${installing.length} recommended apps`)
Promise.all(installing)
.then(() => {
logger.info('all recommended apps installed, redirecting …')
if (apps.length === 0) {
return
}
window.location = this.defaultPageUrl
this.installingApps = true
apps.forEach(app => {
app.loading = true
})
const appIds = apps.map(app => app.id)
logger.debug(`installing ${apps.length} recommended apps`, { appIds })
try {
await axios.post(
generateUrl('settings/apps/enable'),
{ appIds, groups: [] },
{ confirmPassword: PwdConfirmationMode.Strict },
)
apps.forEach(app => {
app.loading = false
app.active = true
})
.catch(error => logger.error('could not install recommended apps', { error }))
logger.info('all recommended apps installed, redirecting …')
window.location = this.defaultPageUrl
} catch (error) {
logger.error('could not install recommended apps', { error })
apps.forEach(app => {
app.loading = false
app.isSelected = false
app.installationError = true
})
this.installingApps = false
}
},
customIcon(appId) {
if (!(appId in recommended) || !recommended[appId].icon) {

View file

@ -4,12 +4,16 @@
*/
import { getCSPNonce } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
import { translate as t } from '@nextcloud/l10n'
import { addPasswordConfirmationInterceptors } from '@nextcloud/password-confirmation'
import Vue from 'vue'
import logger from './logger.js'
import RecommendedApps from './components/setup/RecommendedApps.vue'
addPasswordConfirmationInterceptors(axios)
// eslint-disable-next-line camelcase
__webpack_nonce__ = getCSPNonce()

4
dist/core-common.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5,16 +5,22 @@ SPDX-License-Identifier: BSD-3-Clause
SPDX-License-Identifier: AGPL-3.0-or-later
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
SPDX-FileCopyrightText: escape-html developers
SPDX-FileCopyrightText: debounce developers
SPDX-FileCopyrightText: Varun A P
SPDX-FileCopyrightText: Tobias Koppers @sokra
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
SPDX-FileCopyrightText: Matt Zabriskie
SPDX-FileCopyrightText: Guillaume Chau <guillaume.b.chau@gmail.com>
SPDX-FileCopyrightText: GitHub Inc.
SPDX-FileCopyrightText: Feross Aboukhadijeh
SPDX-FileCopyrightText: Evan You
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
SPDX-FileCopyrightText: David Clark
SPDX-FileCopyrightText: Christoph Wurst
SPDX-FileCopyrightText: Anthony Fu <https://github.com/antfu>
SPDX-FileCopyrightText: @nextcloud/dialogs developers
This file is generated from multiple sources. Included packages:
@ -27,6 +33,9 @@ This file is generated from multiple sources. Included packages:
- @nextcloud/browser-storage
- version: 0.5.0
- license: GPL-3.0-or-later
- @nextcloud/dialogs
- version: 6.4.2
- license: AGPL-3.0-or-later
- semver
- version: 7.7.3
- license: ISC
@ -42,12 +51,24 @@ This file is generated from multiple sources. Included packages:
- @nextcloud/logger
- version: 3.0.3
- license: GPL-3.0-or-later
- @nextcloud/password-confirmation
- version: 5.3.2
- license: MIT
- @nextcloud/paths
- version: 3.0.0
- license: GPL-3.0-or-later
- @nextcloud/router
- version: 3.1.0
- license: GPL-3.0-or-later
- @nextcloud/vue
- version: 8.36.0
- license: AGPL-3.0-or-later
- @vueuse/core
- version: 11.3.0
- license: MIT
- @vueuse/shared
- version: 11.3.0
- license: MIT
- axios
- version: 1.13.4
- license: MIT
@ -57,12 +78,21 @@ This file is generated from multiple sources. Included packages:
- css-loader
- version: 7.1.3
- license: MIT
- debounce
- version: 2.2.0
- license: MIT
- dompurify
- version: 3.3.1
- license: (MPL-2.0 OR Apache-2.0)
- escape-html
- version: 1.0.3
- license: MIT
- floating-vue
- version: 1.0.0-beta.19
- license: MIT
- focus-trap
- version: 7.8.0
- license: MIT
- ieee754
- version: 1.2.1
- license: BSD-3-Clause
@ -75,6 +105,12 @@ This file is generated from multiple sources. Included packages:
- style-loader
- version: 4.0.0
- license: MIT
- tabbable
- version: 6.4.0
- license: MIT
- toastify-js
- version: 1.12.0
- license: MIT
- vue-loader
- version: 15.11.1
- license: MIT

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long