Skip to content

Commit 262dc4b

Browse files
committed
fix(settings): let a failed app token creation surface to the user
addToken swallowed every error from the request and returned null, so the catch in AuthTokenSetup never ran. Creating an app password against a blocked or failing endpoint left the form silently doing nothing. Drop the catch and let the rejection reach the caller, which already logs it and shows an error, the same way updateToken leaves reporting to its callers. Fixes #62680 Signed-off-by: ELHart05 <o.allaoua@esi-sba.dz>
1 parent ea90ea1 commit 262dc4b

2 files changed

Lines changed: 58 additions & 8 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import type { IToken } from './authtoken.ts'
7+
8+
import axios from '@nextcloud/axios'
9+
import { createPinia, setActivePinia } from 'pinia'
10+
import { beforeEach, describe, expect, it, vi } from 'vitest'
11+
import { TokenType, useAuthTokenStore } from './authtoken.ts'
12+
13+
vi.mock('@nextcloud/axios')
14+
vi.mock('@nextcloud/initial-state')
15+
16+
const deviceToken: IToken = {
17+
id: 7,
18+
name: 'Laptop',
19+
type: TokenType.PERMANENT_TOKEN,
20+
lastActivity: 1700000000,
21+
canDelete: true,
22+
canRename: true,
23+
scope: { filesystem: true },
24+
}
25+
26+
describe('store:authtoken addToken', () => {
27+
beforeEach(() => {
28+
setActivePinia(createPinia())
29+
vi.restoreAllMocks()
30+
})
31+
32+
it('keeps the created token', async () => {
33+
vi.spyOn(axios, 'post').mockResolvedValue({
34+
data: { deviceToken, loginName: 'alice', token: 'secret' },
35+
})
36+
37+
const store = useAuthTokenStore()
38+
const response = await store.addToken('Laptop')
39+
40+
expect(response.deviceToken).toBe(deviceToken)
41+
expect(store.tokens).toContain(deviceToken)
42+
})
43+
44+
it('lets a failed request reach the caller so it can be reported', async () => {
45+
vi.spyOn(axios, 'post').mockRejectedValue(new Error('Request failed'))
46+
47+
const store = useAuthTokenStore()
48+
49+
await expect(store.addToken('Laptop')).rejects.toThrow('Request failed')
50+
expect(store.tokens).toHaveLength(0)
51+
})
52+
})

apps/settings/src/store/authtoken.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,13 @@ export const useAuthTokenStore = defineStore('auth-token', {
7575
async addToken(name: string) {
7676
logger.debug('Creating a new app token')
7777

78-
try {
79-
const { data } = await axios.post<ITokenResponse>(BASE_URL, { name, oneTime: true }, { confirmPassword: PwdConfirmationMode.Strict })
78+
// Let the failure reach the caller: AuthTokenSetup is the one that
79+
// reports it, the same way updateToken leaves reporting to its callers.
80+
const { data } = await axios.post<ITokenResponse>(BASE_URL, { name, oneTime: true }, { confirmPassword: PwdConfirmationMode.Strict })
8081

81-
this.tokens.push(data.deviceToken)
82-
logger.debug('App token created')
83-
return data
84-
} catch {
85-
return null
86-
}
82+
this.tokens.push(data.deviceToken)
83+
logger.debug('App token created')
84+
return data
8785
},
8886

8987
/**

0 commit comments

Comments
 (0)