From eadec03e04bacf815f32484166e694b8421d2eef Mon Sep 17 00:00:00 2001 From: John Napier Date: Mon, 21 Jan 2013 15:14:47 -0600 Subject: [PATCH] Fixes Issue #12: Adding the ability to specify member permissions that must be granted in order to authorize access to the requested endpoint. See: https://developer.linkedin.com/documents/authentication#granting --- Readme.md | 5 +++-- lib/linkedin_client.js | 12 +++++++---- package.json | 2 +- tests/linkedin_test.js | 49 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Readme.md b/Readme.md index 0808453..ced505c 100644 --- a/Readme.md +++ b/Readme.md @@ -18,7 +18,8 @@ Params must contain the token. [Using JSON with linkedin API](http://developer.linkedin.com/docs/DOC-1203) -## Example using express.js +## Example using express.js and specifying member permissions +[See "Granting Member Permissions to Your Application"](https://developer.linkedin.com/documents/authentication#granting) ``` javascript var express = require('express') @@ -35,7 +36,7 @@ app.get('/auth', function (req, res) { req.session.token = token; res.render('auth'); - }); + }, ['rw_nus', 'r_network'] /*This AccessToken should be granted these member permissions*/); }); app.post('/message', function (req, res) { diff --git a/lib/linkedin_client.js b/lib/linkedin_client.js index f24261c..f650176 100644 --- a/lib/linkedin_client.js +++ b/lib/linkedin_client.js @@ -44,7 +44,7 @@ module.exports = function (key, secret, redirect) { delete params.token; function requestCallback(callback) { - return function (error, data, response) { + return function (error, data) { if (error) { callback(error, null); } else { @@ -90,12 +90,13 @@ module.exports = function (key, secret, redirect) { * @param {Response} res * @param {Function} callback */ - CLIENT.getAccessToken = function (req, res, callback) { + CLIENT.getAccessToken = function (req, res, callback, permissions) { var parsed_url = url.parse(req.url, true) , protocol = req.socket.encrypted ? 'https' : 'http' , callback_url = protocol + '://' + req.headers.host + parsed_url.pathname , has_token = parsed_url.query && parsed_url.query.oauth_token - , has_secret = req.session && req.session.auth && req.session.auth.linkedin_oauth_token_secret; + , has_secret = req.session && req.session.auth && req.session.auth.linkedin_oauth_token_secret + , scope = permissions instanceof Array ? permissions.join(',') : ""; // var query = url.parse(req.url, true).query // , auth = req.session && req.session.auth; @@ -120,7 +121,10 @@ module.exports = function (key, secret, redirect) { } else { CLIENT.oauth.getOAuthRequestToken( - {oauth_callback: callback_url} + { + oauth_callback: callback_url, + scope: scope + } , function (error, oauth_token, oauth_token_secret, oauth_authorize_url, additional_parameters) { if (error) { callback(error, null); diff --git a/package.json b/package.json index 21875a4..a91edfe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "linkedin-js", "description": "Minimalistic linkedin API client", - "version": "0.1.4", + "version": "0.1.5", "author": "Pau Ramon ", "keywords": ["linkedin"], "dependencies": { "oauth": "0.9.0" }, diff --git a/tests/linkedin_test.js b/tests/linkedin_test.js index d800a2e..8ffab84 100644 --- a/tests/linkedin_test.js +++ b/tests/linkedin_test.js @@ -18,7 +18,6 @@ testosterone assert.equal(_path, 'http://api.linkedin.com/v1/people/id=abcdefg?format=json'); assert.equal(_token, token.oauth_token); assert.equal(_secret, token.oauth_token_secret); - assert.equal(_callback, callback); _callback(); }); @@ -29,6 +28,52 @@ testosterone linkedin_client.apiCall('GET', '/people/id=abcdefg', {token: token}, callback); }) + .add('Adding permissions to `getAccessToken` should not break backwards compatibility', function (done) { + var request = { + url : 'http://somehost.com/somepath', + socket : {encrypted:false}, + headers : { + host: 'localhost' + } + } + , response = {} + , callback = function() {}; + + gently.expect(linkedin_client.oauth, 'getOAuthRequestToken', function(_additionalParams, _callback) { + assert.equal(_additionalParams.scope, ""); + done(); + }); + + linkedin_client.getAccessToken( + request + , response + , callback); + }) + + .add('`getAccessToken` allows member permissions to be specified', function (done) { + var request = { + url : 'http://somehost.com/somepath', + socket : {encrypted:false}, + headers : { + host: 'localhost' + } + } + , response = {} + , callback = function() {} + , permissions = ['r_network', 'rw_nus']; + + gently.expect(linkedin_client.oauth, 'getOAuthRequestToken', function(_additionalParams, _callback) { + assert.equal(_additionalParams.scope, "r_network,rw_nus"); + done(); + }); + + linkedin_client.getAccessToken( + request + , response + , callback + , permissions); + }) + .add('`apiCall` POST', function (done) { var callback; @@ -38,7 +83,6 @@ testosterone assert.equal(_secret, token.oauth_token_secret); assert.deepEqual(_params, {contentType: 'linkedin-html', body: 'hola', '_locale': 'en-US'}); assert.deepEqual(_accept_header, 'application/json; charset=UTF-8'); - assert.equal(_callback, callback); _callback(); }); @@ -60,7 +104,6 @@ testosterone assert.equal(_path, 'http://api.linkedin.com/v1/people-search?keywords=linkedin&format=json'); assert.equal(_token, token.oauth_token); assert.equal(_secret, token.oauth_token_secret); - assert.equal(_callback, callback); _callback(); });