Skip to content

Commit 0b40e8c

Browse files
fix(auth): token() soft-refresh also carries pendingRequests (#4436)
token() refreshed user/abilities/nav but, unlike refreshAbilities(), never reassigned pendingRequests. After the refreshAbilities()->token() onboarding swap, the org-required wall's "request pending" banner and its duplicate-request guard (Request-to-join disabled while pendingRequests) went stale in-session on the join path. /token already returns pendingRequests; token() just dropped it. Add `this.pendingRequests = res.data.pendingRequests || []` so token() is a true soft-refresh superset — fixes proceedToApp, the wall refresh()/requestToJoin(), and every other token() site, and clears a stale banner too. Tests: token() populates + clears pendingRequests. Claude-Session: https://claude.ai/code/session_01XioM62H2iEMLsr686minjn
1 parent b3c4000 commit 0b40e8c

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

src/modules/auth/stores/auth.store.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ export const useAuthStore = defineStore('auth', {
335335
this.auth = true;
336336
this.cookieExpire = res.data.tokenExpiresIn;
337337
this.user = res.data.user;
338+
// Soft-refresh must carry pendingRequests too, so the org-required wall's
339+
// join banner + duplicate-request guard stay accurate after a token()
340+
// soft-refresh (mirrors refreshAbilities()). /token already returns it.
341+
this.pendingRequests = res.data.pendingRequests || [];
338342

339343
if (res.data.abilities) updateAbilities(res.data.abilities);
340344
if (res.data.user.lastLoginAt) {

src/modules/auth/tests/auth.store.unit.tests.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,28 @@ describe('Auth Store', () => {
470470
expect(localStorage.getItem(`${config.cookie.prefix}LastLoginAt`)).toBe(lastLogin);
471471
});
472472

473+
it('should populate pendingRequests from the token response (soft-refresh superset)', async () => {
474+
const authStore = useAuthStore();
475+
const pending = [{ id: 'req-1', organizationId: { name: 'Acme' } }];
476+
axios.get.mockResolvedValueOnce({
477+
data: { user: { id: '789', roles: ['user'] }, tokenExpiresIn: Date.now() + 7200000, pendingRequests: pending },
478+
});
479+
480+
await authStore.token();
481+
482+
expect(authStore.pendingRequests).toEqual(pending);
483+
});
484+
485+
it('should clear a stale pendingRequests when the token response omits them', async () => {
486+
const authStore = useAuthStore();
487+
authStore.pendingRequests = [{ id: 'stale' }];
488+
axios.get.mockResolvedValueOnce({ data: { user: { id: '789', roles: ['user'] }, tokenExpiresIn: 1 } });
489+
490+
await authStore.token();
491+
492+
expect(authStore.pendingRequests).toEqual([]);
493+
});
494+
473495
it('should handle token refresh error without logging to the console', async () => {
474496
const authStore = useAuthStore();
475497
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});

0 commit comments

Comments
 (0)