Don’t block account setup If we’re unable to load your Mailspring ID password

This commit is contained in:
Ben Gotow 2023-11-21 13:42:04 -06:00
parent d69e49a4ff
commit 453416ae04
2 changed files with 31 additions and 10 deletions

View file

@ -10,7 +10,7 @@ import { makeRequest, rootURLForServer } from '../mailspring-api-request';
import { Disposable } from 'event-kit';
// Note this key name is used when migrating to Mailspring Pro accounts from old N1.
const KEYCHAIN_NAME = 'Mailspring Account';
const PASSWORD_NAME = 'Mailspring Account';
export interface IIdentity {
id: string;
@ -41,6 +41,7 @@ export const EMPTY_FEATURE_USAGE = {
class _IdentityStore extends MailspringStore {
_identity: IIdentity = null;
_displayedPasswordError = false;
_disp: Disposable;
constructor() {
@ -98,7 +99,7 @@ class _IdentityStore extends MailspringStore {
async saveIdentity(identity: IIdentity | null) {
if (!identity) {
this._identity = null;
await KeyManager.deletePassword(KEYCHAIN_NAME);
await KeyManager.deletePassword(PASSWORD_NAME);
AppEnv.config.set('identity', null);
return;
}
@ -114,7 +115,7 @@ class _IdentityStore extends MailspringStore {
// Note: We /must/ await this because calling config.set below
// will try to retrieve the password via getPassword.
// If this fails, the app may quit here.
await KeyManager.replacePassword(KEYCHAIN_NAME, nextToken);
await KeyManager.replacePassword(PASSWORD_NAME, nextToken);
}
this._identity = identity;
@ -132,8 +133,20 @@ class _IdentityStore extends MailspringStore {
_onIdentityChanged = async () => {
const value = AppEnv.config.get('identity');
this._identity = value
? { ...value, token: await KeyManager.getPassword(KEYCHAIN_NAME) }
? { ...value, token: await KeyManager.getPassword(PASSWORD_NAME) }
: null;
if (this._identity && !this._identity.token) {
const message = `Your Mailspring ID password could not be loaded from your keychain. Please visit Preferences > Subscription and click "Setup Mailspring ID" to sign in to your Mailspring account again.\n\nYour Mailspring ID email address is ${this._identity.emailAddress}.`;
console.warn(message);
if (!this._displayedPasswordError) {
this._displayedPasswordError = true;
AppEnv.showErrorDialog({ title: 'Please Sign In', message });
}
this._identity = null;
}
this.trigger();
};

View file

@ -5,7 +5,7 @@ interface KeySet {
[key: string]: string;
}
const { safeStorage } = require("@electron/remote");
const { safeStorage } = require('@electron/remote');
const configCredentialsKey = 'credentials';
@ -18,7 +18,6 @@ const configCredentialsKey = 'credentials';
* and every key we want to access.
*/
class KeyManager {
async deleteAccountSecrets(account: Account) {
try {
const keys = await this._getKeyHash();
@ -90,8 +89,17 @@ class KeyManager {
let raw = '{}';
const encryptedCredentials = AppEnv.config.get(configCredentialsKey);
// Check for different null values to prevent issues if a migration from keytar has failed
if (encryptedCredentials !== undefined && encryptedCredentials !== null && encryptedCredentials !== "null") {
raw = await safeStorage.decryptString(Buffer.from(encryptedCredentials, "utf-8"));
if (
encryptedCredentials !== undefined &&
encryptedCredentials !== null &&
encryptedCredentials !== 'null'
) {
try {
raw = await safeStorage.decryptString(Buffer.from(encryptedCredentials, 'utf-8'));
} catch (err) {
console.error('Mailspring encountered an error reading passwords from the keychain.');
console.error(err);
}
}
try {
return JSON.parse(raw) as KeySet;
@ -101,7 +109,7 @@ class KeyManager {
}
async _writeKeyHash(keys: KeySet) {
const enrcyptedCredentials = await safeStorage.encryptString(JSON.stringify(keys))
const enrcyptedCredentials = await safeStorage.encryptString(JSON.stringify(keys));
AppEnv.config.set(configCredentialsKey, enrcyptedCredentials);
}
@ -117,7 +125,7 @@ class KeyManager {
if (clickedButton == 0) {
const shell = require('electron').shell;
shell.openExternal("https://community.getmailspring.com/t/password-management-error/199")
shell.openExternal('https://community.getmailspring.com/t/password-management-error/199');
}
// tell the app to exit and rethrow the error to ensure code relying