Stop syncing email account credentials to the cloud

This commit is contained in:
Ben Gotow 2017-09-10 12:04:22 -07:00
parent 30885be8e4
commit 44b00cbbf5
9 changed files with 45 additions and 52 deletions

View file

@ -5,7 +5,7 @@ import {RetinaImg} from 'nylas-component-kit';
import {NylasAPIRequest, Actions} from 'nylas-exports';
import OnboardingActions from '../onboarding-actions';
import {runAuthValidation} from '../onboarding-helpers';
import {buildAndValidateAccount} from '../onboarding-helpers';
import FormErrorMessage from '../form-error-message';
import AccountTypes from '../account-types'
@ -99,10 +99,10 @@ const CreatePageForForm = (FormComponent) => {
this.setState({submitting: true});
runAuthValidation(accountInfo)
.then(({account, cloudToken}) => {
buildAndValidateAccount(accountInfo)
.then(({account}) => {
OnboardingActions.moveToPage('account-onboarding-success')
OnboardingActions.accountJSONReceived(account, cloudToken)
OnboardingActions.accountJSONReceived(account)
})
.catch((err) => {
Actions.recordUserEvent('Email Account Auth Failed', {

View file

@ -40,6 +40,21 @@ function base64url(inBuffer) {
.replace(/\//g, '_'); // Convert '/' to '_'
}
function idForAccount(emailAddress, connectionSettings) {
// changing your connection security settings / ports shouldn't blow
// away everything and trash your metadata. Just look at critiical fields.
// (Me adding more connection settings fields shouldn't break account Ids either!)
const settingsThatCouldChangeMailContents = {
imap_username: connectionSettings.imap_username,
imap_host: connectionSettings.imap_host,
smtp_username: connectionSettings.smtp_username,
smtp_host: connectionSettings.smtp_host,
}
const idString = `${emailAddress}${JSON.stringify(settingsThatCouldChangeMailContents)}`;
return crypto.createHash('sha256').update(idString, 'utf8').digest('hex');
}
export function makeGmailOAuthRequest(sessionKey) {
return makeRequest({
server: 'accounts',
@ -54,20 +69,15 @@ export async function authIMAPForGmail(serverTokenResponse) {
// created an account object in the database and tested it. All we
// need to do is save it locally, since we're confident Gmail will be
// accessible from the local sync worker.
const {id, email_address, provider, connection_settings, account_token, xoauth_refresh_token, name} = serverTokenResponse;
const {emailAddress, refreshToken} = serverTokenResponse;
const settings = expandAccountInfoWithCommonSettings({email: emailAddress, refreshToken, type: 'gmail'});
// Todo: clean up the serialization so this translation from K2 JSON isn't necessary.
return {
account: {
id,
provider,
name,
emailAddress: email_address,
settings: Object.assign({}, connection_settings, {
xoauth_refresh_token,
}),
},
cloudToken: account_token,
id: idForAccount(emailAddress, settings),
provider: 'gmail',
name,
settings,
emailAddress,
};
}
@ -79,11 +89,11 @@ export function buildGmailAuthURL(sessionKey) {
return `${rootURLForServer('accounts')}/auth/gmail?state=${sessionKey}`;
}
export async function runAuthValidation(accountInfo) {
export async function buildAndValidateAccount(accountInfo) {
const {username, type, email, name} = accountInfo;
const data = {
id: 'temp',
id: idForAccount(email, accountInfo),
provider: type,
name: name,
emailAddress: email,
@ -114,21 +124,7 @@ export async function runAuthValidation(accountInfo) {
const proc = new MailsyncProcess(NylasEnv.getLoadSettings(), IdentityStore.identity(), data);
const {account} = await proc.test();
delete data.id;
const {id, account_token} = await makeRequest({
server: 'accounts',
path: `/auth`,
method: 'POST',
timeout: 1000 * 180, // Same timeout as server timeout (most requests are faster than 90s, but server validation can be slow in some cases)
body: data,
auth: false,
})
return {
account: Object.assign({}, account, {id}),
cloudToken: account_token,
};
return account;
}
export function isValidHost(value) {

View file

@ -139,10 +139,10 @@ class OnboardingStore extends NylasStore {
}, 1000);
}
_onAccountJSONReceived = async (json, cloudToken) => {
_onAccountJSONReceived = async (json) => {
try {
const isFirstAccount = AccountStore.accounts().length === 0;
AccountStore.addAccountFromJSON(json, cloudToken);
AccountStore.addAccountFromJSON(json);
Actions.recordUserEvent('Email Account Auth Succeeded', {
provider: json.provider,

View file

@ -25,8 +25,8 @@ export default class AccountSettingsPageGmail extends React.Component {
this._gmailAuthUrl = buildGmailAuthURL(this._sessionKey)
}
onSuccess({account, cloudToken}) {
OnboardingActions.accountJSONReceived(account, cloudToken);
onSuccess(account) {
OnboardingActions.accountJSONReceived(account);
}
render() {

View file

@ -5,6 +5,7 @@ import ReactDOM from 'react-dom'
import classnames from 'classnames';
import networkErrors from 'chromium-net-errors';
import {rootURLForServer} from '../flux/nylas-api-request';
import RetinaImg from './retina-img'
class InitialLoadingCover extends React.Component {
@ -42,7 +43,7 @@ class InitialLoadingCover extends React.Component {
if (this.props.error) {
message = this.props.error;
} else if (this.state.slow) {
message = "Still trying to reach id.getmailspring.com…";
message = `Still trying to reach ${rootURLForServer('identity')}`;
} else {
message = ' '
}

View file

@ -85,8 +85,8 @@ class CrashTracker {
});
}
_keyFor({id, settings, cloudToken}) {
return JSON.stringify({id, settings, cloudToken});
_keyFor({id, settings}) {
return JSON.stringify({id, settings});
}
_appendCrashToHistory(fullAccountJSON) {

View file

@ -137,8 +137,7 @@ class AccountStore extends NylasStore {
// the account is added, but we want to be on the safe side.
delete a.settings.imap_password;
delete a.settings.smtp_password;
delete a.settings.xoauth_refresh_token;
delete a.cloudToken;
delete a.settings.refresh_token;
});
NylasEnv.config.set(configAccountsKey, configAccounts);
NylasEnv.config.set(configVersionKey, this._version);
@ -204,14 +203,14 @@ class AccountStore extends NylasStore {
this._save()
}
addAccountFromJSON = (json, cloudToken) => {
addAccountFromJSON = (json) => {
if (!json.emailAddress || !json.provider) {
throw new Error(`Returned account data is invalid: ${JSON.stringify(json)}`)
}
// send the account JSON and cloud token to the KeyManager,
// which gives us back a version with no secrets.
const cleanJSON = KeyManager.extractAccountSecrets(json, cloudToken);
const cleanJSON = KeyManager.extractAccountSecrets(json);
this._loadAccounts();

View file

@ -29,12 +29,11 @@ class KeyManager {
delete keys[`${account.emailAddress}-imap`];
delete keys[`${account.emailAddress}-smtp`];
delete keys[`${account.emailAddress}-refresh-token`];
delete keys[`${account.emailAddress}-cloud`];
return this._writeKeyHash(keys);
});
}
extractAccountSecrets(accountJSON, cloudToken) {
extractAccountSecrets(accountJSON) {
const next = Object.assign({}, accountJSON);
this._try(() => {
const keys = this._getKeyHash();
@ -42,9 +41,8 @@ class KeyManager {
delete next.settings.imap_password;
keys[`${accountJSON.emailAddress}-smtp`] = next.settings.smtp_password;
delete next.settings.smtp_password;
keys[`${accountJSON.emailAddress}-refresh-token`] = next.settings.xoauth_refresh_token;
delete next.settings.xoauth_refresh_token;
keys[`${accountJSON.emailAddress}-cloud`] = cloudToken;
keys[`${accountJSON.emailAddress}-refresh-token`] = next.settings.refresh_token;
delete next.settings.refresh_token;
return this._writeKeyHash(keys);
});
return next;
@ -55,8 +53,7 @@ class KeyManager {
const keys = this._getKeyHash();
next.settings.imap_password = keys[`${accountJSON.emailAddress}-imap`];
next.settings.smtp_password = keys[`${accountJSON.emailAddress}-smtp`];
next.settings.xoauth_refresh_token = keys[`${accountJSON.emailAddress}-refresh-token`];
next.cloudToken = keys[`${accountJSON.emailAddress}-cloud`];
next.settings.refresh_token = keys[`${accountJSON.emailAddress}-refresh-token`];
return next;
}

@ -1 +1 @@
Subproject commit e3aa42eadbf0ae6606ee28167f0505d4715731fa
Subproject commit 542475dcecd4b8ef0e873b855460f71f0f82127c