From f3482ce0206d38d937fd1f975fafd91dfeabbf19 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sat, 17 Oct 2026 00:13:46 +0200 Subject: [PATCH] fix: remember restored sign-ins only when the restoring account is remembered --- app/(main)/admin/_tabs/policy.tsx | 2 +- lib/__tests__/account-archive-client.test.ts | 18 +++++++++++++++++- lib/account-archive-client.ts | 9 ++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/app/(main)/admin/_tabs/policy.tsx b/app/(main)/admin/_tabs/policy.tsx index 4b6e94eb1..c5b410022 100644 --- a/app/(main)/admin/_tabs/policy.tsx +++ b/app/(main)/admin/_tabs/policy.tsx @@ -39,7 +39,7 @@ const FEATURE_GATE_LABELS: Partial { }); const result = await restoreArchive([entry('a@example.com', 'right'), entry('b@example.com', 'stale'), entry('c@example.com')], true); expect(auth.signIn).toHaveBeenCalledTimes(2); - expect(auth.signIn).toHaveBeenCalledWith(generateAccountId('a@example.com', server), 'right', true); + expect(auth.signIn).toHaveBeenCalledWith(generateAccountId('a@example.com', server), 'right', false); expect(result).toMatchObject({ added: 3, signedIn: 1, signInFailed: 1, waiting: 2 }); }); + it('remembers the restored sign-ins only when the restoring account is remembered', async () => { + auth.signIn.mockResolvedValue(true); + const owner = add('owner@example.com', 'basic'); + useAccountStore.getState().updateAccount(owner, { rememberMe: false }); + useAccountStore.setState({ activeAccountId: owner }); + await restoreArchive([entry('a@example.com', 'right')], true); + expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('a@example.com', server), 'right', false); + + useAccountStore.getState().updateAccount(owner, { rememberMe: true }); + await restoreArchive([entry('b@example.com', 'right')], true); + expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('b@example.com', server), 'right', true); + + await restoreArchive([entry('c@example.com', 'right')], false); + expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('c@example.com', server), 'right', false); + }); + it('does not sign in again to an account already connected here', async () => { const id = add('a@example.com', 'basic'); auth.clients.set(id, { getBasicPassword: () => 'right' }); diff --git a/lib/account-archive-client.ts b/lib/account-archive-client.ts index 3eb83c826..c17a14b15 100644 --- a/lib/account-archive-client.ts +++ b/lib/account-archive-client.ts @@ -75,8 +75,15 @@ export function restoreAccounts(archived: ArchivedAccount[]): { added: number; u * Restores the list, then signs in one by one to the accounts saved with a * password that are not signed in here yet. An account whose password no * longer works keeps waiting for a sign-in by hand. + * + * A restored sign-in is remembered only when the server allows it and the + * account doing the restore was itself signed in with "Remember me": on a + * shared computer, restoring must not leave long-lived sessions behind. */ -export async function restoreArchive(archived: ArchivedAccount[], rememberMe: boolean) { +export async function restoreArchive(archived: ArchivedAccount[], rememberMeAllowed: boolean) { + const accounts = useAccountStore.getState(); + const active = accounts.accounts.find(a => a.id === accounts.activeAccountId); + const rememberMe = rememberMeAllowed && !!active?.rememberMe; const result = restoreAccounts(archived); let signedIn = 0, signInFailed = 0; for (const entry of archived) {