fix(auth-failure): Warn of disconnect on 403s, fix logic

This commit is contained in:
Ben Gotow 2016-02-23 18:35:24 -08:00
parent 7e96a169a2
commit 9ef84e476a
3 changed files with 33 additions and 19 deletions

View file

@ -123,7 +123,7 @@ class SendLaterPopover extends Component {
<button className={className}> <button className={className}>
<RetinaImg name="icon-composer-sendlater.png" mode={RetinaImg.Mode.ContentIsMask}/> <RetinaImg name="icon-composer-sendlater.png" mode={RetinaImg.Mode.ContentIsMask}/>
{dateInterpretation} {dateInterpretation}
<span data-reactid=".s.0.0.1">&nbsp;</span> <span>&nbsp;</span>
<RetinaImg name="icon-composer-dropdown.png" mode={RetinaImg.Mode.ContentIsMask}/> <RetinaImg name="icon-composer-dropdown.png" mode={RetinaImg.Mode.ContentIsMask}/>
</button> </button>
); );

View file

@ -3,6 +3,7 @@ fs = require 'fs'
Actions = require '../src/flux/actions' Actions = require '../src/flux/actions'
NylasAPI = require '../src/flux/nylas-api' NylasAPI = require '../src/flux/nylas-api'
Thread = require '../src/flux/models/thread' Thread = require '../src/flux/models/thread'
AccountStore = require '../src/flux/stores/account-store'
DatabaseStore = require '../src/flux/stores/database-store' DatabaseStore = require '../src/flux/stores/database-store'
DatabaseTransaction = require '../src/flux/stores/database-transaction' DatabaseTransaction = require '../src/flux/stores/database-transaction'
@ -45,12 +46,19 @@ describe "NylasAPI", ->
expect(DatabaseStore.find).not.toHaveBeenCalled() expect(DatabaseStore.find).not.toHaveBeenCalled()
expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalled() expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalled()
describe "handle401", -> describe "handleAuthenticationFailure", ->
it "should post a notification", -> it "should post a notification", ->
spyOn(Actions, 'postNotification') spyOn(Actions, 'postNotification')
NylasAPI._handle401('/threads/1234') NylasAPI._handleAuthenticationFailure('/threads/1234', 'token')
expect(Actions.postNotification).toHaveBeenCalled() 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", -> describe "handleModelResponse", ->
beforeEach -> beforeEach ->

View file

@ -11,7 +11,7 @@ async = require 'async'
# A 0 code is when an error returns without a status code. These are # A 0 code is when an error returns without a status code. These are
# things like "ESOCKETTIMEDOUT" # things like "ESOCKETTIMEDOUT"
TimeoutErrorCode = 0 TimeoutErrorCode = 0
PermanentErrorCodes = [400, 403, 404, 405, 500] PermanentErrorCodes = [400, 401, 403, 404, 405, 500]
CancelledErrorCode = -123 CancelledErrorCode = -123
SampleTemporaryErrorCode = 504 SampleTemporaryErrorCode = 504
@ -127,6 +127,12 @@ class NylasAPI
NylasEnv.config.onDidChange('env', @_onConfigChanged) NylasEnv.config.onDidChange('env', @_onConfigChanged)
@_onConfigChanged() @_onConfigChanged()
if NylasEnv.isMainWindow()
Actions.notificationActionTaken.listen ({notification, action}) ->
if action.id is '401:unlink'
Actions.switchPreferencesTab('Accounts')
Actions.openPreferences()
_onConfigChanged: => _onConfigChanged: =>
prev = {@AppID, @APIRoot, @APITokens} prev = {@AppID, @APIRoot, @APITokens}
@ -191,8 +197,8 @@ class NylasAPI
if err.response if err.response
if err.response.statusCode is 404 and options.returnsModel if err.response.statusCode is 404 and options.returnsModel
handlePromise = @_handleModel404(options.url) handlePromise = @_handleModel404(options.url)
if err.response.statusCode is 401 if err.response.statusCode in [401, 403]
handlePromise = @_handle401(options.url) handlePromise = @_handleAuthenticationFailure(options.url, options.auth?.user)
if err.response.statusCode is 400 if err.response.statusCode is 400
NylasEnv.reportError(err) NylasEnv.reportError(err)
handlePromise.finally -> handlePromise.finally ->
@ -227,14 +233,21 @@ class NylasAPI
else else
return Promise.resolve() 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 Actions.postNotification
type: 'error' type: 'error'
tag: '401' tag: '401'
sticky: true sticky: true
message: "Nylas can no longer authenticate with your mail provider. You message: "Nylas can no longer authenticate with #{email}. You
will not be able to send or receive mail. Please unlink your will not be able to send or receive mail. Please remove the
account and sign in again.", account and sign in again.",
icon: 'fa-sign-out' icon: 'fa-sign-out'
actions: [{ actions: [{
default: true default: true
@ -243,13 +256,6 @@ class NylasAPI
id: '401:unlink' 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() return Promise.resolve()
# Returns a Promise that resolves when any parsed out models (if any) # Returns a Promise that resolves when any parsed out models (if any)
@ -362,7 +368,7 @@ class NylasAPI
@_optimisticChangeTracker.decrement(klass, id) @_optimisticChangeTracker.decrement(klass, id)
accessTokenForAccountId: (aid) -> accessTokenForAccountId: (aid) ->
AccountStore = require './stores/account-store' AccountStore ?= require './stores/account-store'
AccountStore.tokenForAccountId(aid) AccountStore.tokenForAccountId(aid)
# Returns a promise that will resolve if the user is successfully authed # Returns a promise that will resolve if the user is successfully authed