mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-13 20:12:54 -07:00
fix: retry transient AniList safeStorage failures
This commit is contained in:
@@ -38,6 +38,24 @@ function createPassthroughStorage(): SafeStorageLike {
|
||||
};
|
||||
}
|
||||
|
||||
function createTransientUnavailableStorage(): SafeStorageLike & {
|
||||
setAvailable: (next: boolean) => void;
|
||||
} {
|
||||
let available = false;
|
||||
return {
|
||||
isEncryptionAvailable: () => available,
|
||||
encryptString: (value: string) => Buffer.from(`enc:${value}`, 'utf-8'),
|
||||
decryptString: (value: Buffer) => {
|
||||
const raw = value.toString('utf-8');
|
||||
return raw.startsWith('enc:') ? raw.slice(4) : raw;
|
||||
},
|
||||
getSelectedStorageBackend: () => (available ? 'gnome_libsecret' : 'unknown'),
|
||||
setAvailable(next: boolean) {
|
||||
available = next;
|
||||
},
|
||||
} as SafeStorageLike & { setAvailable: (next: boolean) => void };
|
||||
}
|
||||
|
||||
test('anilist token store saves and loads encrypted token', () => {
|
||||
const filePath = createTempTokenFile();
|
||||
const store = createAnilistTokenStore(filePath, createLogger(), createStorage(true));
|
||||
@@ -61,6 +79,27 @@ test('anilist token store refuses to persist token when encryption unavailable',
|
||||
assert.equal(store.loadToken(), null);
|
||||
});
|
||||
|
||||
test('anilist token store retries safeStorage after transient encryption unavailability', () => {
|
||||
const filePath = createTempTokenFile();
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
JSON.stringify({
|
||||
encryptedToken: Buffer.from('enc:stored-token', 'utf-8').toString('base64'),
|
||||
updatedAt: Date.now(),
|
||||
}),
|
||||
'utf-8',
|
||||
);
|
||||
const storage = createTransientUnavailableStorage();
|
||||
const store = createAnilistTokenStore(filePath, createLogger(), storage);
|
||||
|
||||
assert.equal(store.loadToken(), null);
|
||||
storage.setAvailable(true);
|
||||
|
||||
assert.equal(store.loadToken(), 'stored-token');
|
||||
assert.equal(store.saveToken('new-token'), true);
|
||||
assert.equal(store.loadToken(), 'new-token');
|
||||
});
|
||||
|
||||
test('anilist token store migrates legacy plaintext to encrypted', () => {
|
||||
const filePath = createTempTokenFile();
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -69,7 +69,6 @@ export function createAnilistTokenStore(
|
||||
`AniList token encryption unavailable: safeStorage.isEncryptionAvailable() is false. ` +
|
||||
`Context: ${getSafeStorageDebugContext()}`,
|
||||
);
|
||||
safeStorageUsable = false;
|
||||
return false;
|
||||
}
|
||||
const probe = storage.encryptString('__subminer_anilist_probe__');
|
||||
@@ -77,7 +76,6 @@ export function createAnilistTokenStore(
|
||||
notifyUser(
|
||||
'AniList token encryption probe failed: safeStorage.encryptString() returned plaintext bytes.',
|
||||
);
|
||||
safeStorageUsable = false;
|
||||
return false;
|
||||
}
|
||||
const roundTrip = storage.decryptString(probe);
|
||||
@@ -85,7 +83,6 @@ export function createAnilistTokenStore(
|
||||
notifyUser(
|
||||
'AniList token encryption probe failed: encrypt/decrypt round trip returned unexpected content.',
|
||||
);
|
||||
safeStorageUsable = false;
|
||||
return false;
|
||||
}
|
||||
safeStorageUsable = true;
|
||||
@@ -96,7 +93,6 @@ export function createAnilistTokenStore(
|
||||
`AniList token encryption unavailable: safeStorage probe threw an error. ` +
|
||||
`Context: ${getSafeStorageDebugContext()}`,
|
||||
);
|
||||
safeStorageUsable = false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user