diff --git a/lib/auth.js b/lib/auth.js index 7522cf7..a2e4972 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -18,11 +18,11 @@ const authClient = new Model({ _refreshToken: '', _tokenRefreshPromise: null, - _getBearerToken: function() { + async _getBearerToken() { console.log('Getting bearer token'); if (this._bearerToken) { console.info('Already had a bearer token'); - return Promise.resolve(this._bearerToken); + return this._bearerToken; } else { var url = config.host + '/oauth/token'; @@ -31,21 +31,19 @@ const authClient = new Model({ 'client_id': config.clientAppID, }; - return makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) - .then(function(request) { - var token = this._handleNewBearerToken(request); - console.info('Got bearer token', token.slice(-6)); - return token; - }.bind(this)) - .catch(function(request) { - // You're probably not signed in. - console.error('Failed to get bearer token'); - return apiClient.handleError(request); - }); + try { + const response = await makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) + const token = this._handleNewBearerToken(response); + console.info('Got bearer token', token.slice(-6)); + return token; + } catch (error) { + console.error('Failed to get bearer token'); + return apiClient.handleError(error); + } } }, - _handleNewBearerToken: function(request) { + _handleNewBearerToken(request) { var response = JSON.parse(request.text); this._bearerToken = response.access_token; @@ -58,43 +56,42 @@ const authClient = new Model({ return this._bearerToken; }, - _bearerTokenIsExpired: function() { + _bearerTokenIsExpired() { return Date.now() >= this._bearerTokenExpiration - BEARER_TOKEN_EXPIRATION_ALLOWANCE; }, - _refreshBearerToken: function() { + async _makeRefreshTokenRequest(data) { + var url = config.host + '/oauth/token'; + let token = ''; + try { + const response = await makeHTTPRequest('POST', url, data, config.jsonHeaders) + token = this._handleNewBearerToken(response); + console.info('Refreshed bearer token', token.slice(-6)); + } catch (error) { + console.error('Failed to refresh bearer token'); + apiClient.handleError(request); + } + this._tokenRefreshPromise = null; + return token; + }, + + async _refreshBearerToken() { if (this._tokenRefreshPromise === null) { console.log('Refreshing expired bearer token'); - var url = config.host + '/oauth/token'; - var data = { grant_type: 'refresh_token', refresh_token: this._refreshToken, client_id: config.clientAppID, }; - this._tokenRefreshPromise = makeHTTPRequest('POST', url, data, config.jsonHeaders) - .then(function(request) { - var token = this._handleNewBearerToken(request); - console.info('Refreshed bearer token', token.slice(-6)); - return token; - }.bind(this)) - .catch(function(request) { - console.error('Failed to refresh bearer token'); - apiClient.handleError(request); - return ''; - }) - .then(function(token) { - this._tokenRefreshPromise = null; - return token - }.bind(this)); + this._tokenRefreshPromise = this._makeRefreshTokenRequest(); } return this._tokenRefreshPromise; }, - _deleteBearerToken: function() { + _deleteBearerToken() { this._bearerToken = ''; delete apiClient.headers.Authorization; this._bearerTokenExpiration = NaN; @@ -102,224 +99,206 @@ const authClient = new Model({ console.log('Deleted bearer token'); }, - _getSession: function() { + async _getSession() { console.log('Getting session'); - return apiClient.get('/me') - .then(function(users) { - var user = users[0]; - console.info('Got session', user.login, user.id); - return user; - }) - .catch(function(error) { - console.error('Failed to get session'); - throw error; - }); + try { + const [user] = await apiClient.get('/me') + console.info('Got session', user.login, user.id); + return user; + } catch (error) { + console.error('Failed to get session'); + throw error; + } }, - register: function(given) { - var originalArguments = arguments; - return this.checkCurrent().then(function(user) { - if (user) { - return this.signOut().then(function() { - return this.register.apply(this, originalArguments); - }.bind(this)); - } else { - console.log('Registering new account', given.login); - var registrationRequest = getCSRFToken(config.host).then(function(token) { - var data = { - authenticity_token: token, - user: { - login: given.login, - email: given.email, - password: given.password, - credited_name: given.credited_name, - global_email_communication: given.global_email_communication, - project_id: given.project_id, - beta_email_communication: given.beta_email_communication, - project_email_communication: given.project_email_communication, - }, - }; - var url = config.host + '/users'; - return makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) - .then(function() { - return this._getBearerToken().then(function() { - return this._getSession().then(function(user) { - console.info('Registered account', user.login, user.id); - return user; - }); - }.bind(this)); - }.bind(this)) - .catch(function(request) { - console.error('Failed to register'); - return apiClient.handleError(request); - }); - }.bind(this)); + async _makeRegistrationRequest(data) { + try { + const url = config.host + '/users'; + await makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) + await this._getBearerToken(); + const user = await this._getSession(); + console.info('Registered account', user.login, user.id); + return user; + } catch (error) { + console.error('Failed to register'); + return apiClient.handleError(error); + } + }, - this.update({ - _currentUserPromise: registrationRequest.catch(function() { - return null; - }), - }); + async register(given) { + const user = await this.checkCurrent(); + if (user) { + await this.signOut() + return this.register(given); + } else { + const token = await getCSRFToken(config.host); + const data = { + authenticity_token: token, + user: { + login: given.login, + email: given.email, + password: given.password, + credited_name: given.credited_name, + global_email_communication: given.global_email_communication, + project_id: given.project_id, + beta_email_communication: given.beta_email_communication, + project_email_communication: given.project_email_communication, + }, + }; - return registrationRequest; - } - }.bind(this)); + const registrationRequest = this._makeRegistrationRequest(data); + this.update({ + _currentUserPromise: registrationRequest.catch(function() { + return null; + }), + }); + + return registrationRequest; + } }, - checkCurrent: function() { + async _getUser() { + try { + const token = await this._getBearerToken(); + return this._getSession(); + } catch (error) { + // Nobody's signed in. This isn't an error. + console.info('No current user'); + return null; + } + }, + + async checkCurrent() { if (!this._currentUserPromise) { console.log('Checking current user'); this.update({ - _currentUserPromise: this._getBearerToken() - .then(function() { - return this._getSession(); - }.bind(this)) - .catch(function() { - // Nobody's signed in. This isn't an error. - console.info('No current user'); - return null; - }), + _currentUserPromise: this._getUser() }); } return this._currentUserPromise; }, - checkBearerToken: function() { - var awaitBearerToken; + async checkBearerToken() { + let awaitBearerToken; if (this._bearerTokenIsExpired()) { - awaitBearerToken = this._refreshBearerToken(); + awaitBearerToken = await this._refreshBearerToken(); } else { - awaitBearerToken = Promise.resolve(this._bearerToken); + awaitBearerToken = this._bearerToken; } return awaitBearerToken; }, - signIn: function(credentials) { - var originalArguments = arguments; - return this.checkCurrent().then(function(user) { - if (user) { - return this.signOut().then(function() { - return this.signIn.apply(this, originalArguments); - }.bind(this)); - } else { - console.log('Signing in', credentials.login); - var signInRequest = getCSRFToken(config.host).then(function(token) { - var url = config.host + '/users/sign_in'; - - var data = { - authenticity_token: token, - user: { - login: credentials.login, - password: credentials.password, - remember_me: true, - }, - }; - - return makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) - .then(function() { - return this._getBearerToken().then(function() { - return this._getSession().then(function(user) { - console.info('Signed in', user.login, user.id); - return user; - }.bind(this)); - }.bind(this)); - }.bind(this)) - .catch(function(request) { - console.error('Failed to sign in'); - return apiClient.handleError(request); - }); - }.bind(this)); - - this.update({ - _currentUserPromise: signInRequest.catch(function() { - return null; - }), - }); - - return signInRequest; - } - }.bind(this)); - }, - - changePassword: function(given) { - return this.checkCurrent().then(function(user) { - if (user) { - return getCSRFToken(config.host).then(function(token) { - var data = { - authenticity_token: token, - user: { - current_password: given.current, - password: given.replacement, - password_confirmation: given.replacement, - }, - }; - - const url = config.host + '/users'; - return makeCredentialHTTPRequest('PUT', url, data, config.jsonHeaders) - .then(function() { - // Resetting the password changes the underlying cookie session data - // need to sign out and back in to refresh - return this.signOut(); - }.bind(this)) - .then(function() { - return this.signIn({ - login: user.login, - password: given.replacement, - }); - }.bind(this)); - }.bind(this)); - } else { - throw new Error('No signed-in user to change the password for'); - } - }.bind(this)); + async _makeSignInRequest(data) { + try { + const url = config.host + '/users/sign_in'; + await makeCredentialHTTPRequest('POST', url, data, config.jsonHeaders) + await this._getBearerToken() + const user = await this._getSession() + console.info('Signed in', user.login, user.id); + return user; + } catch (error) { + console.error('Failed to sign in'); + return apiClient.handleError(error); + } }, - requestPasswordReset: function(given) { - return getCSRFToken(config.host).then(function(token) { - var data = { + async signIn(credentials) { + const user = await this.checkCurrent() + if (user) { + await this.signOut(); + return this.signIn(credentials); + } else { + console.log('Signing in', credentials.login); + const token = await getCSRFToken(config.host) + const data = { authenticity_token: token, user: { - email: given.email, + login: credentials.login, + password: credentials.password, + remember_me: true, }, }; - return apiClient.post('/../users/password', data, config.jsonHeaders); - }.bind(this)); + const signInRequest = this._makeSignInRequest(data); + this.update({ + _currentUserPromise: signInRequest.catch(function() { + return null; + }), + }); + + return signInRequest; + } }, - resetPassword: function(given) { - return getCSRFToken(config.host).then(function(authToken) { - var data = { - authenticity_token: authToken, + async changePassword(given) { + const user = await this.checkCurrent(); + if (user) { + const token = await getCSRFToken(config.host); + const data = { + authenticity_token: token, user: { - password: given.password, - password_confirmation: given.confirmation, - reset_password_token: given.token, + current_password: given.current, + password: given.replacement, + password_confirmation: given.replacement, }, }; - const url = config.host + '/users/password'; - return makeCredentialHTTPRequest('PUT', url, data, config.jsonHeaders); - }.bind(this)); + const url = config.host + '/users'; + await makeCredentialHTTPRequest('PUT', url, data, config.jsonHeaders); + // Resetting the password changes the underlying cookie session data + // need to sign out and back in to refresh + await this.signOut(); + return this.signIn({ + login: user.login, + password: given.replacement, + }); + } else { + throw new Error('No signed-in user to change the password for'); + } + }, + + async requestPasswordReset(given) { + const token = await getCSRFToken(config.host); + const data = { + authenticity_token: token, + user: { + email: given.email, + }, + }; + + return apiClient.post('/../users/password', data, config.jsonHeaders); }, - disableAccount: function() { + async resetPassword(given) { + const authToken = await getCSRFToken(config.host); + const data = { + authenticity_token: authToken, + user: { + password: given.password, + password_confirmation: given.confirmation, + reset_password_token: given.token, + }, + }; + + const url = config.host + '/users/password'; + return makeCredentialHTTPRequest('PUT', url, data, config.jsonHeaders); + }, + + async disableAccount() { console.log('Disabling account'); - return this.checkCurrent().then(function(user) { - if (user) { - return user.delete().then(function() { - this._deleteBearerToken(); - this.update({ - _currentUserPromise: Promise.resolve(null), - }); - console.info('Disabled account'); - return null; - }.bind(this)); - } else { - throw new Error('Failed to disable account; not signed in'); - } - }.bind(this)); + const user = await this.checkCurrent(); + if (user) { + await user.delete(); + this._deleteBearerToken(); + this.update({ + _currentUserPromise: Promise.resolve(null), + }); + console.info('Disabled account'); + return null; + } else { + throw new Error('Failed to disable account; not signed in'); + } }, async signOut() { @@ -353,17 +332,16 @@ const authClient = new Model({ } }, - unsubscribeEmail: function(given) { - return getCSRFToken(config.host).then(function(token) { - var url = config.host + '/unsubscribe'; + async unsubscribeEmail(given) { + const token = await getCSRFToken(config.host) + const url = config.host + '/unsubscribe'; - var data = { - authenticity_token: token, - email: given.email, - }; + const data = { + authenticity_token: token, + email: given.email, + }; - return makeHTTPRequest('POST', url, data, config.jsonHeaders); - }.bind(this)); + return makeHTTPRequest('POST', url, data, config.jsonHeaders); }, }); diff --git a/package-lock.json b/package-lock.json index df168f9..5d9dff4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "panoptes-client", - "version": "5.3.0", + "version": "6.0.0-rc-1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "panoptes-client", - "version": "5.3.0", + "version": "6.0.0-rc-1", "license": "Apache-2.0", "dependencies": { "local-storage": "^2.0.0",