fix: enhance account management by updating existing accounts and improving session handling
This commit is contained in:
+21
-4
@@ -58,13 +58,30 @@ export const useAccountStore = create<AccountState>()(
|
|||||||
|
|
||||||
addAccount: (entry) => {
|
addAccount: (entry) => {
|
||||||
const state = get();
|
const state = get();
|
||||||
if (state.accounts.length >= MAX_ACCOUNTS) {
|
|
||||||
throw new Error(`Maximum of ${MAX_ACCOUNTS} accounts reached`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = generateAccountId(entry.username, entry.serverUrl);
|
const id = generateAccountId(entry.username, entry.serverUrl);
|
||||||
if (state.accounts.some((a) => a.id === id)) {
|
if (state.accounts.some((a) => a.id === id)) {
|
||||||
return id; // already exists, return existing id
|
// Already exists — update mutable fields and return existing id
|
||||||
|
set((s) => ({
|
||||||
|
accounts: s.accounts.map((a) =>
|
||||||
|
a.id === id
|
||||||
|
? {
|
||||||
|
...a,
|
||||||
|
rememberMe: entry.rememberMe,
|
||||||
|
isConnected: entry.isConnected,
|
||||||
|
hasError: entry.hasError,
|
||||||
|
errorMessage: undefined,
|
||||||
|
lastLoginAt: entry.lastLoginAt,
|
||||||
|
authMode: entry.authMode,
|
||||||
|
}
|
||||||
|
: a
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.accounts.length >= MAX_ACCOUNTS) {
|
||||||
|
throw new Error(`Maximum of ${MAX_ACCOUNTS} accounts reached`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cookieSlot = state.getNextCookieSlot();
|
const cookieSlot = state.getNextCookieSlot();
|
||||||
|
|||||||
+37
-17
@@ -288,6 +288,33 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
});
|
});
|
||||||
accountStore.setActiveAccount(accountId);
|
accountStore.setActiveAccount(accountId);
|
||||||
|
|
||||||
|
// Update account entry in case it already existed (addAccount is a no-op for existing accounts)
|
||||||
|
accountStore.updateAccount(accountId, {
|
||||||
|
rememberMe: !!rememberMe,
|
||||||
|
isConnected: true,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: undefined,
|
||||||
|
lastLoginAt: Date.now(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store session cookie BEFORE setting isAuthenticated to avoid a race
|
||||||
|
// condition: setting isAuthenticated triggers navigation to the main page,
|
||||||
|
// whose checkAuth() would try to read the cookie before it was stored.
|
||||||
|
if (rememberMe) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/auth/session?slot=${cookieSlot}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ serverUrl, username, password: effectivePassword, slot: cookieSlot }),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
debug.error('Failed to store session: server returned', res.status);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
debug.error('Failed to store session:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
set({
|
set({
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@@ -297,6 +324,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
identities,
|
identities,
|
||||||
primaryIdentity,
|
primaryIdentity,
|
||||||
authMode: 'basic',
|
authMode: 'basic',
|
||||||
|
rememberMe: !!rememberMe,
|
||||||
accessToken: null,
|
accessToken: null,
|
||||||
tokenExpiresAt: null,
|
tokenExpiresAt: null,
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
@@ -312,23 +340,6 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
});
|
});
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
|
|
||||||
if (rememberMe) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(`/api/auth/session?slot=${cookieSlot}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ serverUrl, username, password: effectivePassword, slot: cookieSlot }),
|
|
||||||
});
|
|
||||||
if (res.ok) {
|
|
||||||
set({ rememberMe: true });
|
|
||||||
} else {
|
|
||||||
debug.error('Failed to store session: server returned', res.status);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
debug.error('Failed to store session:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
debug.error('Login error:', error);
|
debug.error('Login error:', error);
|
||||||
@@ -537,6 +548,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
username: nextAccount.username,
|
username: nextAccount.username,
|
||||||
client: nextClient,
|
client: nextClient,
|
||||||
authMode: nextAccount.authMode,
|
authMode: nextAccount.authMode,
|
||||||
|
rememberMe: nextAccount.rememberMe,
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
error: null,
|
error: null,
|
||||||
activeAccountId: nextAccount.id,
|
activeAccountId: nextAccount.id,
|
||||||
@@ -740,6 +752,11 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!targetClient) {
|
if (!targetClient) {
|
||||||
|
accountStore.updateAccount(accountId, {
|
||||||
|
isConnected: false,
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'Unable to restore session',
|
||||||
|
});
|
||||||
set({ isLoading: false });
|
set({ isLoading: false });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -756,6 +773,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
username: targetAccount.username,
|
username: targetAccount.username,
|
||||||
client: targetClient,
|
client: targetClient,
|
||||||
authMode: targetAccount.authMode,
|
authMode: targetAccount.authMode,
|
||||||
|
rememberMe: targetAccount.rememberMe,
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
error: null,
|
error: null,
|
||||||
activeAccountId: accountId,
|
activeAccountId: accountId,
|
||||||
@@ -872,6 +890,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
identities,
|
identities,
|
||||||
primaryIdentity,
|
primaryIdentity,
|
||||||
authMode: targetAccount.authMode,
|
authMode: targetAccount.authMode,
|
||||||
|
rememberMe: targetAccount.rememberMe,
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
error: null,
|
error: null,
|
||||||
activeAccountId: targetId,
|
activeAccountId: targetId,
|
||||||
@@ -903,6 +922,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
identities,
|
identities,
|
||||||
primaryIdentity,
|
primaryIdentity,
|
||||||
authMode: acc.authMode,
|
authMode: acc.authMode,
|
||||||
|
rememberMe: acc.rememberMe,
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
error: null,
|
error: null,
|
||||||
activeAccountId: id,
|
activeAccountId: id,
|
||||||
|
|||||||
Reference in New Issue
Block a user