Skip to content

Commit 04ca640

Browse files
committed
clean up
1 parent dd2ce4c commit 04ca640

2 files changed

Lines changed: 42 additions & 22 deletions

File tree

libs/services/state-service/stateMigration.service.spec.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -617,29 +617,48 @@ describe("StateMigrationService", () => {
617617
secureStorage.store.set(`${userId}_oktaToken`, "okta-token");
618618
});
619619

620-
it("calls migrateKeytarPassword for each old {userId}_* key", async () => {
620+
it("does not call migrateKeytarPassword for keys that are already readable", async () => {
621+
// beforeEach seeds ldapPassword, entraIdKey, entraKey, oktaToken directly so
622+
// secureStorageService.get returns a value — migrateKeytarPassword should be skipped
623+
// for those keys.
621624
await svc.migrate();
622625

623626
const calledKeys = passwords.migrateKeytarPassword.mock.calls.map(
624627
(c: [string, string]) => c[1],
625628
);
626-
expect(calledKeys).toEqual(
627-
expect.arrayContaining([
628-
`${userId}_ldapPassword`,
629-
`${userId}_entraIdKey`,
630-
`${userId}_entraKey`,
631-
`${userId}_oktaToken`,
632-
]),
629+
expect(calledKeys).not.toContain(`${userId}_ldapPassword`);
630+
expect(calledKeys).not.toContain(`${userId}_entraIdKey`);
631+
expect(calledKeys).not.toContain(`${userId}_oktaToken`);
632+
});
633+
634+
it("calls migrateKeytarPassword when old key is unreadable (UTF-8 keytar blob)", async () => {
635+
// Remove the readable value to simulate a key that exists in the credential store
636+
// but cannot be decoded by desktop_core (UTF-8 blob).
637+
secureStorage.store.delete(`${userId}_ldapPassword`);
638+
639+
await svc.migrate();
640+
641+
const calledKeys = passwords.migrateKeytarPassword.mock.calls.map(
642+
(c: [string, string]) => c[1],
633643
);
644+
expect(calledKeys).toContain(`${userId}_ldapPassword`);
634645
});
635646

636-
it("copies old keys to flat keys via secureStorageService", async () => {
647+
it("copies old keys to flat keys when the flat key is absent", async () => {
637648
await svc.migrate();
638649

639650
expect(secureStorage.store.get(SecureStorageKeys.ldap)).toBe("ldap-pass");
640651
expect(secureStorage.store.get(SecureStorageKeys.okta)).toBe("okta-token");
641652
});
642653

654+
it("does not overwrite a flat key that already has a current value", async () => {
655+
secureStorage.store.set(SecureStorageKeys.ldap, "current-ldap-pass");
656+
657+
await svc.migrate();
658+
659+
expect(secureStorage.store.get(SecureStorageKeys.ldap)).toBe("current-ldap-pass");
660+
});
661+
643662
it("prefers _entraIdKey over _entraKey and keeps both old keys intact", async () => {
644663
await svc.migrate();
645664

libs/services/state-service/stateMigration.service.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,9 @@ export class StateMigrationService {
275275
*
276276
* Strategy: call migrateKeytarPassword on each old {userId}_* key first, which re-encodes
277277
* the blob from UTF-8 to UTF-16 in-place (making it readable by desktop_core). Then copy
278-
* to the flat key via secureStorageService and remove the old key. On macOS/Linux,
279-
* migrateKeytarPassword is a no-op so the get/save/remove path handles everything.
278+
* to the flat key only if it is not already set — preserving any current value written by
279+
* the running app. Old keys are kept intact.
280+
* On macOS/Linux, migrateKeytarPassword is a no-op so the get/save path handles everything.
280281
*/
281282
protected async migrateStateFrom6To7(): Promise<void> {
282283
const clientId = await this.storageService.get<string>("activeUserId");
@@ -297,18 +298,18 @@ export class StateMigrationService {
297298

298299
const written = new Set<string>();
299300
for (const { old: oldKey, new: newKey } of oldSecretKeys) {
300-
// Re-encode the UTF-8 keytar blob to UTF-16 in-place so desktop_core can read it.
301-
await passwords.migrateKeytarPassword(SECURE_STORAGE_SERVICE_NAME, oldKey);
302-
303-
if (written.has(newKey)) {
304-
continue;
305-
}
306-
307-
const value = await this.secureStorageService.get<string>(oldKey);
308-
if (value != null) {
309-
await this.secureStorageService.save(newKey, value);
310-
written.add(newKey);
301+
const existing = await this.secureStorageService.get<string>(newKey);
302+
if (existing == null) {
303+
let value = await this.secureStorageService.get<string>(oldKey);
304+
if (value == null) {
305+
await passwords.migrateKeytarPassword(SECURE_STORAGE_SERVICE_NAME, oldKey);
306+
value = await this.secureStorageService.get<string>(oldKey);
307+
}
308+
if (value != null && !written.has(newKey)) {
309+
await this.secureStorageService.save(newKey, value);
310+
}
311311
}
312+
written.add(newKey);
312313
}
313314
}
314315

0 commit comments

Comments
 (0)