mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-08 02:13:24 +00:00
fix(keychain): gate credential-store startup access
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { getKeychainStartupDecision } from './keychainStartup';
|
||||
|
||||
describe('getKeychainStartupDecision', () => {
|
||||
it('defers persistent hydration and shows the explanation after an update', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '1.0.5',
|
||||
approvedVersion: '1.0.4',
|
||||
accessGranted: true,
|
||||
promptDismissed: false
|
||||
})).toEqual({
|
||||
deferKeychainHydration: true,
|
||||
showKeychainPrompt: true
|
||||
});
|
||||
});
|
||||
|
||||
it('hydrates automatically after the current version was explicitly approved', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '1.0.5',
|
||||
approvedVersion: '1.0.5',
|
||||
accessGranted: true,
|
||||
promptDismissed: false
|
||||
})).toEqual({
|
||||
deferKeychainHydration: false,
|
||||
showKeychainPrompt: false
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the explanation on first run without touching the credential store', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '1.0.5',
|
||||
approvedVersion: '',
|
||||
accessGranted: false,
|
||||
promptDismissed: false
|
||||
})).toEqual({
|
||||
deferKeychainHydration: true,
|
||||
showKeychainPrompt: true
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps a deliberately deferred session quiet on later launches', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '1.0.5',
|
||||
approvedVersion: '1.0.5',
|
||||
accessGranted: false,
|
||||
promptDismissed: true
|
||||
})).toEqual({
|
||||
deferKeychainHydration: true,
|
||||
showKeychainPrompt: false
|
||||
});
|
||||
});
|
||||
|
||||
it('reoffers the explanation after a later update even if the previous one was deferred', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '1.0.6',
|
||||
approvedVersion: '1.0.5',
|
||||
accessGranted: false,
|
||||
promptDismissed: true
|
||||
})).toEqual({
|
||||
deferKeychainHydration: true,
|
||||
showKeychainPrompt: true
|
||||
});
|
||||
});
|
||||
|
||||
it('does not repeat a deferred prompt when the version API is unavailable', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: false,
|
||||
appVersion: '',
|
||||
approvedVersion: '',
|
||||
accessGranted: false,
|
||||
promptDismissed: true
|
||||
})).toEqual({
|
||||
deferKeychainHydration: true,
|
||||
showKeychainPrompt: false
|
||||
});
|
||||
});
|
||||
|
||||
it('never gates portable pairing on credential-store access', () => {
|
||||
expect(getKeychainStartupDecision({
|
||||
portable: true,
|
||||
appVersion: '1.0.5',
|
||||
approvedVersion: '',
|
||||
accessGranted: false,
|
||||
promptDismissed: false
|
||||
})).toEqual({
|
||||
deferKeychainHydration: false,
|
||||
showKeychainPrompt: false
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
export type KeychainStartupState = {
|
||||
portable: boolean;
|
||||
appVersion: string;
|
||||
approvedVersion: string;
|
||||
accessGranted: boolean;
|
||||
promptDismissed: boolean;
|
||||
};
|
||||
|
||||
export type KeychainStartupDecision = {
|
||||
deferKeychainHydration: boolean;
|
||||
showKeychainPrompt: boolean;
|
||||
};
|
||||
|
||||
export const getKeychainStartupDecision = ({
|
||||
portable,
|
||||
appVersion,
|
||||
approvedVersion,
|
||||
accessGranted,
|
||||
promptDismissed
|
||||
}: KeychainStartupState): KeychainStartupDecision => {
|
||||
if (portable) {
|
||||
return {
|
||||
deferKeychainHydration: false,
|
||||
showKeychainPrompt: false
|
||||
};
|
||||
}
|
||||
|
||||
const versionChanged = Boolean(appVersion) && approvedVersion !== appVersion;
|
||||
return {
|
||||
deferKeychainHydration: !accessGranted || versionChanged,
|
||||
showKeychainPrompt: versionChanged || (!accessGranted && !promptDismissed)
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user