Skip to content
Browse files

Spread improved error handling love. Fix google example

  • Loading branch information...
1 parent 4b03a35 commit c501bc9468f2635dfe7aa146eee72f810ca5b781 @bnoguchi committed Apr 22, 2012
View
2 example/server.js
@@ -212,7 +212,7 @@ everyauth.linkedin
everyauth.google
.appId(conf.google.clientId)
.appSecret(conf.google.clientSecret)
- .scope('https://www.google.com/m8/feeds/')
+ .scope('https://www.googleapis.com/auth/userinfo.profile https://www.google.com/m8/feeds/')
.findOrCreateUser( function (sess, accessToken, extra, googleUser) {
googleUser.refreshToken = extra.refresh_token;
googleUser.expiresIn = extra.expires_in;
View
22 lib/modules/37signals.js
@@ -29,7 +29,23 @@ oauthModule.submodule('37signals')
})
return p;
})
-
- .convertErr( function (err) {
- return new Error(err.data);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var _37sigResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ _37sigResponse.statusCode
+ , _37sigResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
});
View
9 lib/modules/everymodule.js
@@ -242,11 +242,11 @@ var everyModule = module.exports = {
*/
, breakTo: function (sequenceName) {
// TODO Garbage collect the abandoned sequence
- var seq = this._stepSequences[sequenceName]
- , args = Array.prototype.slice.call(arguments, 1);
+ var seq = this._stepSequences[sequenceName];
if (!seq) {
throw new Error('You are trying to break to a sequence named `' + sequenceName + '`, but there is no sequence with that name in the auth module, `' + this.name + '`.');
}
+ var args = Array.prototype.slice.call(arguments, 1);
seq = seq.materialize();
seq.initialArgs = args;
throw seq;
@@ -355,10 +355,11 @@ everyModule.performRedirect( function(res, location) {
});
everyModule.moduleTimeout(10000);
-everyModule.moduleErrback( function (err, data) {
+everyModule.moduleErrback( function (err, seqValues) {
if (! (err instanceof Error)) {
console.log('Warning: Try to pass only Errors');
err = new Error(JSON.stringify(err));
}
- data.next(err);
+ var next = seqValues.next;
+ next(err);
});
View
24 lib/modules/facebook.js
@@ -44,15 +44,31 @@ oauthModule.submodule('facebook')
fieldsQuery = "?fields=" + this.fields();
}
this.oauth.get(this.apiHost() + '/me' + fieldsQuery, accessToken, function (err, data) {
- if (err)
- return p.fail(err);
+ if (err) return p.fail(err);
var oauthUser = JSON.parse(data);
p.fulfill(oauthUser);
})
return p;
})
- .convertErr( function (data) {
- return new Error(JSON.parse(data.data).error.message);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var facebookResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ facebookResponse.statusCode
+ , facebookResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
});
fb.mobile = function (isMobile) {
View
28 lib/modules/foursquare.js
@@ -23,18 +23,34 @@ oauthModule.submodule('foursquare')
, queryParams = { oauth_token: accessToken }
request.get({ url: userUrl, qs: queryParams}, function (err, res, body) {
if (err) {
+ err.extra = {res: res, data: body};
return promise.fail(err);
}
- if (res.statusCode !== 200) {
- return promise.fail(body);
+ if (parseInt(res.statusCode/100, 10) !== 2) {
+ return promise.fail({extra: {data: body, res: res}});
}
var oauthUser = JSON.parse(body).response.user;
return promise.fulfill(oauthUser);
});
return promise;
})
-
- .convertErr( function (data) {
- var errMsg = JSON.parse(data.data).meta.errorDetail;
- return new Error(errMsg);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var foursquareResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ foursquareResponse.statusCode
+ , foursquareResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
});
View
20 lib/modules/github.js
@@ -27,4 +27,24 @@ oauthModule.submodule('github')
p.fulfill(oauthUser);
})
return p;
+ })
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var ghResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ ghResponse.statusCode
+ , ghResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
});
View
49 lib/modules/google.js
@@ -22,8 +22,20 @@ oauthModule.submodule('google')
.entryPath('/auth/google')
.callbackPath('/auth/google/callback')
- .authQueryParam('scope', function () {
- return this._scope && this.scope();
+ .authQueryParam({
+ access_type: 'offline'
+ , approval_prompt: 'force'
+ , scope: function () {
+ return this._scope && this.scope();
+ }
+ })
+
+ .addToSession( function (sess, auth) {
+ this._super(sess, auth);
+ if (auth.refresh_token) {
+ sess.auth[this.name].refreshToken = auth.refresh_token;
+ sess.auth[this.name].expiresInSeconds = parseInt(auth.expires_in, 10);
+ }
})
.authCallbackDidErr( function (req) {
@@ -43,19 +55,38 @@ oauthModule.submodule('google')
throw new Error("You must configure handleAuthCallbackError if you are not using express");
}
})
- .convertErr( function (data) {
- return new Error(data.data.match(/H1>(.+)<\/H1/)[1]);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var googleResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ googleResponse.statusCode
+ , googleResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
})
.fetchOAuthUser( function (accessToken) {
var promise = this.Promise()
, userUrl = 'https://www.googleapis.com/oauth2/v1/userinfo'
- , queryParams = { oauth_token: accessToken, alt: 'json' };
- console.log(queryParams);
- request.get({url: userUrl, qs: queryParams}, function (err, res, body) {
+ , queryParams = { access_token: accessToken, alt: 'json' };
+ request.get({
+ url: userUrl
+ , qs: queryParams
+ }, function (err, res, body) {
if (err) return promise.fail(err);
- if (res.statusCode !== 200) {
- return promise.fail(body);
+ if (parseInt(res.statusCode/100, 10) !== 2) {
+ return promise.fail({extra: {data: body, res: res}});
}
promise.fulfill(JSON.parse(body));
});
View
31 lib/modules/linkedin.js
@@ -34,16 +34,33 @@ oauthModule.submodule('linkedin')
.fetchOAuthUser( function (accessToken, accessTokenSecret, params) {
var promise = this.Promise();
- this.oauth.get(this.apiHost() + '/people/~:(id,first-name,last-name,headline,location:(name,country:(code)),industry,num-connections,num-connections-capped,summary,specialties,proposal-comments,associations,honors,interests,positions,publications,patents,languages,skills,certifications,educations,three-current-positions,three-past-positions,num-recommenders,recommendations-received,phone-numbers,im-accounts,twitter-accounts,date-of-birth,main-address,member-url-resources,picture-url,site-standard-profile-request:(url),api-standard-profile-request:(url,headers),public-profile-url)', accessToken, accessTokenSecret, function (err, data) {
- if (err) return promise.fail(err);
+ this.oauth.get(this.apiHost() + '/people/~:(id,first-name,last-name,headline,location:(name,country:(code)),industry,num-connections,num-connections-capped,summary,specialties,proposal-comments,associations,honors,interests,positions,publications,patents,languages,skills,certifications,educations,three-current-positions,three-past-positions,num-recommenders,recommendations-received,phone-numbers,im-accounts,twitter-accounts,date-of-birth,main-address,member-url-resources,picture-url,site-standard-profile-request:(url),api-standard-profile-request:(url,headers),public-profile-url)', accessToken, accessTokenSecret, function (err, data, res) {
+ if (err) {
+ err.extra = {data: data, res: res}
+ return promise.fail(err);
+ }
var oauthUser = JSON.parse(data);
promise.fulfill(oauthUser);
});
return promise;
})
- .convertErr( function (data) {
-// var errJson = JSON.parse(data.data)
-// , errMsg = errJson.message;
- var errMsg = data.data;
- return new Error("LinkedIn sent back a " + data.statusCode + " response with data = " + errMsg);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var linkedInResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ linkedInResponse.statusCode
+ , linkedInResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
+ } else {
+ console.error(err);
+ throw new Error('Unsupported error type');
+ }
});
View
9 lib/modules/oauth.js
@@ -102,8 +102,7 @@ everyModule.submodule('oauth')
var p = this.Promise();
this.oauth.getOAuthRequestToken({ oauth_callback: this._myHostname + this._callbackPath }, function (err, token, tokenSecret, params) {
if (err) {
- if (!err.data || -1 == err.data.indexOf('Invalid / expired Token'))
- return p.fail(err);
+ return p.fail(err);
}
p.fulfill(token, tokenSecret);
});
@@ -163,10 +162,8 @@ everyModule.submodule('oauth')
})
.getAccessToken( function (reqToken, reqTokenSecret, verifier) {
var promise = this.Promise();
- this.oauth.getOAuthAccessToken(reqToken, reqTokenSecret, verifier, function (err, accessToken, accessTokenSecret, params) {
- if (err && !~(err.data.indexOf('Invalid / expired Token'))) {
- return promise.fail(err);
- }
+ this.oauth.getOAuthAccessToken(reqToken + 'kkk', reqTokenSecret, verifier, function (err, accessToken, accessTokenSecret, params) {
+ if (err) return promise.fail(err);
promise.fulfill(accessToken, accessTokenSecret, params);
});
return promise;
View
7 lib/modules/oauth2.js
@@ -183,8 +183,11 @@ everyModule.submodule('oauth2')
}
opts[paramsVia] = params;
request[this._accessTokenHttpMethod](opts, function (err, res, body) {
- if (err) return p.fail(err);
- if (parseInt(res.statusCode / 100) != 2) return p.fail(body);
+ if (err) {
+ err.extra = {data: body, res: res};
+ return p.fail(err);
+ }
+ if (parseInt(res.statusCode / 100) != 2) return p.fail({extra: {res: res, data: body}});
var resType = res.headers['content-type']
, data;
if (resType.substring(0, 10) === 'text/plain') {
View
28 lib/modules/twitter.js
@@ -10,8 +10,11 @@ oauthModule.submodule('twitter')
.authorizePath('/oauth/authenticate')
.fetchOAuthUser( function (accessToken, accessTokenSecret, params) {
var promise = this.Promise();
- this.oauth.get(this.apiHost() + '/users/show.json?user_id=' + params.user_id, accessToken, accessTokenSecret, function (err, data) {
- if (err) return promise.fail(err);
+ this.oauth.get(this.apiHost() + '/users/show.json?user_id=' + params.user_id, accessToken, accessTokenSecret, function (err, data, res) {
+ if (err) {
+ err.extra = {data: data, res: res};
+ return promise.fail(err);
+ }
var oauthUser = JSON.parse(data);
promise.fulfill(oauthUser);
});
@@ -31,10 +34,23 @@ oauthModule.submodule('twitter')
throw new Error("You must configure handleAuthCallbackError if you are not using express");
}
})
- .convertErr( function (data) {
- if (data.data.charAt(0) === '{') { // If we have JSON
- return new Error(JSON.parse(data.data).error);
+ .moduleErrback( function (err, seqValues) {
+ if (err instanceof Error) {
+ var next = seqValues.next;
+ return next(err);
+ } else if (err.extra) {
+ var twitterResponse = err.extra.res
+ , serverResponse = seqValues.res;
+ serverResponse.writeHead(
+ twitterResponse.statusCode
+ , twitterResponse.headers);
+ serverResponse.end(err.extra.data);
+ } else if (err.statusCode) {
+ var serverResponse = seqValues.res;
+ serverResponse.writeHead(err.statusCode);
+ serverResponse.end(err.data);
} else {
- return new Error(data.data.match(/<error>(.+)<\/error>/)[1]);
+ console.error(err);
+ throw new Error('Unsupported error type');
}
});
View
41 lib/step.js
@@ -18,15 +18,23 @@ Step.prototype = {
, promises = this.promises
, block = this.block
, _module = this.module
+ , stepName = this.name
, self = this
- , errorCallback = function(error){
- // ensure that seq.values are always passed back to moduleErrback
- (this.errback || _module._moduleErrback).call(self, error, seq.values)
+ , errorCallback = function (error) {
+ // Ensure that seq.values are always passed back to moduleErrback
+ if (self.errback) {
+ self.errback(error, seq.values);
+ } else if (_module._moduleErrback) {
+ _module._moduleErrback(error, seq.values);
+ } else {
+ throw new Error('Missing module or step errback');
+ }
};
- if (this.debug)
+ if (this.debug) {
console.log('starting step - ' + this.name);
+ }
var args = this._unwrapArgs(seq);
@@ -43,7 +51,7 @@ Step.prototype = {
// Add _super access
_module._super = function () {
- var step = this.__proto__._steps[self.name];
+ var step = this.__proto__._steps[stepName];
if (!step) return;
var superArgs = arguments.length ? arguments : args;
step.block.apply(this, superArgs);
@@ -60,19 +68,17 @@ Step.prototype = {
return;
} else {
// Else, we have a regular exception
- // TODO Scope this fn
errorCallback(breakTo);
}
}
if (promises && promises.length &&
'undefined' === typeof ret) {
- // TODO Scope this fn
errorCallback(
- new Error('Step ' + this.name + ' of `' + _module.name +
- '` is promising: ' + promises.join(', ') +
+ new Error('Step ' + this.name + ' of `' + _module.name +
+ '` is promising: ' + promises.join(', ') +
' ; however, the step returns nothing. ' +
- 'Fix the step by returning the expected values OR ' +
+ 'Fix the step by returning the expected values OR ' +
'by returning a Promise that promises said values.')
);
}
@@ -86,10 +92,11 @@ Step.prototype = {
: this.module.Promise(ret)
: this.module.Promise([ret]);
- ret.callback( function () {
- if (seq.debug)
+ if (seq.debug) {
+ ret.callback( function () {
console.log('...finished step');
- });
+ });
+ }
var convertErr = _module._convertErr;
if (convertErr) {
@@ -108,7 +115,6 @@ Step.prototype = {
};
}
- // TODO Scope this fn -- i.e., errorCallback?
ret.errback(errorCallback);
ret.callback( function () {
@@ -122,12 +128,11 @@ Step.prototype = {
});
ret.timeback( function () {
- ret.fail(new Error('Step ' + self.name + ' of `' + _module.name + '` module timed out.'));
+ ret.fail(new Error('Step ' + stepName + ' of `' + _module.name + '` module timed out.'));
});
- var timeoutMillis = this.timeout ||
- _module.moduleTimeout();
- ret.timeout(timeoutMillis);
+ var timeoutMs = this.timeout || _module.moduleTimeout();
+ ret.timeout(timeoutMs);
return ret;
}

0 comments on commit c501bc9

Please sign in to comment.
Something went wrong with that request. Please try again.