From 9ef84e476a714ea9bf7071f9d80717f911884ae8 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 23 Feb 2016 18:35:24 -0800 Subject: [PATCH] fix(auth-failure): Warn of disconnect on 403s, fix logic --- .../send-later/lib/send-later-popover.jsx | 2 +- spec/nylas-api-spec.coffee | 14 ++++++-- src/flux/nylas-api.coffee | 36 +++++++++++-------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/internal_packages/send-later/lib/send-later-popover.jsx b/internal_packages/send-later/lib/send-later-popover.jsx index c47a8b46e..42f5656bf 100644 --- a/internal_packages/send-later/lib/send-later-popover.jsx +++ b/internal_packages/send-later/lib/send-later-popover.jsx @@ -123,7 +123,7 @@ class SendLaterPopover extends Component { ); diff --git a/spec/nylas-api-spec.coffee b/spec/nylas-api-spec.coffee index c3939ffa2..1142dd25b 100644 --- a/spec/nylas-api-spec.coffee +++ b/spec/nylas-api-spec.coffee @@ -3,6 +3,7 @@ fs = require 'fs' Actions = require '../src/flux/actions' NylasAPI = require '../src/flux/nylas-api' Thread = require '../src/flux/models/thread' +AccountStore = require '../src/flux/stores/account-store' DatabaseStore = require '../src/flux/stores/database-store' DatabaseTransaction = require '../src/flux/stores/database-transaction' @@ -45,12 +46,19 @@ describe "NylasAPI", -> expect(DatabaseStore.find).not.toHaveBeenCalled() expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalled() - describe "handle401", -> + describe "handleAuthenticationFailure", -> it "should post a notification", -> spyOn(Actions, 'postNotification') - NylasAPI._handle401('/threads/1234') + NylasAPI._handleAuthenticationFailure('/threads/1234', 'token') expect(Actions.postNotification).toHaveBeenCalled() - expect(Actions.postNotification.mostRecentCall.args[0].message).toEqual("Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please unlink your account and sign in again.") + expect(Actions.postNotification.mostRecentCall.args[0].message.trim()).toEqual("Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please remove the account and sign in again.") + + it "should include the email address if possible", -> + spyOn(AccountStore, 'tokenForAccountId').andReturn('token') + spyOn(Actions, 'postNotification') + NylasAPI._handleAuthenticationFailure('/threads/1234', 'token') + expect(Actions.postNotification).toHaveBeenCalled() + expect(Actions.postNotification.mostRecentCall.args[0].message.trim()).toEqual("Nylas can no longer authenticate with #{AccountStore.accounts()[0].emailAddress}. You will not be able to send or receive mail. Please remove the account and sign in again.") describe "handleModelResponse", -> beforeEach -> diff --git a/src/flux/nylas-api.coffee b/src/flux/nylas-api.coffee index b041dd992..fb9207bc0 100644 --- a/src/flux/nylas-api.coffee +++ b/src/flux/nylas-api.coffee @@ -11,7 +11,7 @@ async = require 'async' # A 0 code is when an error returns without a status code. These are # things like "ESOCKETTIMEDOUT" TimeoutErrorCode = 0 -PermanentErrorCodes = [400, 403, 404, 405, 500] +PermanentErrorCodes = [400, 401, 403, 404, 405, 500] CancelledErrorCode = -123 SampleTemporaryErrorCode = 504 @@ -127,6 +127,12 @@ class NylasAPI NylasEnv.config.onDidChange('env', @_onConfigChanged) @_onConfigChanged() + if NylasEnv.isMainWindow() + Actions.notificationActionTaken.listen ({notification, action}) -> + if action.id is '401:unlink' + Actions.switchPreferencesTab('Accounts') + Actions.openPreferences() + _onConfigChanged: => prev = {@AppID, @APIRoot, @APITokens} @@ -191,8 +197,8 @@ class NylasAPI if err.response if err.response.statusCode is 404 and options.returnsModel handlePromise = @_handleModel404(options.url) - if err.response.statusCode is 401 - handlePromise = @_handle401(options.url) + if err.response.statusCode in [401, 403] + handlePromise = @_handleAuthenticationFailure(options.url, options.auth?.user) if err.response.statusCode is 400 NylasEnv.reportError(err) handlePromise.finally -> @@ -227,14 +233,21 @@ class NylasAPI else return Promise.resolve() - _handle401: (modelUrl) -> + _handleAuthenticationFailure: (modelUrl, apiToken) -> + AccountStore ?= require './stores/account-store' + account = AccountStore.accounts().find (account) -> + AccountStore.tokenForAccountId(account.id) is apiToken + + email = "your mail provider" + email = account.emailAddress if account + Actions.postNotification type: 'error' tag: '401' sticky: true - message: "Nylas can no longer authenticate with your mail provider. You - will not be able to send or receive mail. Please unlink your - account and sign in again.", + message: "Nylas can no longer authenticate with #{email}. You + will not be able to send or receive mail. Please remove the + account and sign in again.", icon: 'fa-sign-out' actions: [{ default: true @@ -243,13 +256,6 @@ class NylasAPI id: '401:unlink' }] - unless @_notificationUnlisten - handler = ({notification, action}) -> - if action.id is '401:unlink' - {ipcRenderer} = require 'electron' - ipcRenderer.send('command', 'application:reset-config-and-relaunch') - @_notificationUnlisten = Actions.notificationActionTaken.listen(handler, @) - return Promise.resolve() # Returns a Promise that resolves when any parsed out models (if any) @@ -362,7 +368,7 @@ class NylasAPI @_optimisticChangeTracker.decrement(klass, id) accessTokenForAccountId: (aid) -> - AccountStore = require './stores/account-store' + AccountStore ?= require './stores/account-store' AccountStore.tokenForAccountId(aid) # Returns a promise that will resolve if the user is successfully authed