diff --git a/lib/common/connection.js b/lib/common/connection.js index 53680871532..e7911521f9b 100644 --- a/lib/common/connection.js +++ b/lib/common/connection.js @@ -75,7 +75,13 @@ module.exports.Token = Token; * Create a connection object. * * @param {object} opts - Configuration options. - * @param {array} opts.scopes - Scopes required for access. + * @param {array=} opts.scopes - Scopes required for access. + * @param {string=} opts.keyFilename - Full path to the JSON key downloaded + * from the Google Developers Console. Alternatively, you may provide a + * `credentials` object. + * @param {object=} opts.credentials - Credentials object. + * @param {string} opts.credentials.client_email + * @param {string} opts.credentials.private_key * * @example * var SCOPES = [ @@ -93,6 +99,15 @@ function Connection(opts) { this.isConnecting = false; this.waitQueue = []; + + if (opts.credentials) { + if (opts.credentials.client_email && opts.credentials.private_key) { + this.credentials = opts.credentials; + } else { + throw new Error('A credentials object must contain the following keys: ' + + 'client_email, private_key'); + } + } } /** @@ -129,7 +144,7 @@ Connection.prototype.connect = function(callback) { */ Connection.prototype.fetchToken = function(callback) { var that = this; - if (!this.opts.keyFilename) { + if (!this.opts.keyFilename && !this.credentials) { // We should be on GCE, try to retrieve token from the metadata server. req({ method: 'get', diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index b53ea8122e8..475f69263b9 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -76,8 +76,11 @@ var SCOPES = [ * @param {object=} options * @param {string} options.projectId - Dataset ID. This is your project ID from * the Google Developers Console. - * @param {string} options.keyFilename - Full path to the JSON key downloaded - * from the Google Developers Console. + * @param {string=} options.keyFilename - Full path to the JSON key downloaded + * from the Google Developers Console. Alternatively, you may provide a + * `credentials` object. + * @param {object=} options.credentials - Credentials object, used in place of + * a `keyFilename`. * @param {string} options.namespace - Namespace to isolate transactions to. * * @example @@ -90,6 +93,7 @@ function Dataset(options) { options = options || {}; this.connection = new conn.Connection({ + credentials: options.credentials, keyFilename: options.keyFilename, scopes: SCOPES }); diff --git a/lib/pubsub/index.js b/lib/pubsub/index.js index d977b690d7d..8bbfe7c2cd1 100644 --- a/lib/pubsub/index.js +++ b/lib/pubsub/index.js @@ -219,8 +219,11 @@ Topic.prototype.del = function(callback) { * Represents connection to Google Cloud Pub/Sub API. * @param {string} opts.projectId Google Developers Console Project ID. * @param {string} opts.email Service account email. - * @param {string} opts.pemFilePath Path to the pem file that contains your - * private key. + * @param {string=} options.keyFilename - Full path to the JSON key downloaded + * from the Google Developers Console. Alternatively, you may provide a + * `credentials` object. + * @param {object=} options.credentials - Credentials object, used in place of + * a `keyFilename`. */ function Connection(opts) { opts = opts || {}; @@ -228,6 +231,7 @@ function Connection(opts) { this.id = id; this.conn = new conn.Connection({ + credentials: opts.credentials, keyFilename: opts.keyFilename, scopes: SCOPES }); diff --git a/lib/storage/index.js b/lib/storage/index.js index 61a866c76f1..9bf06fc4a4d 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -92,8 +92,11 @@ BufferStream.prototype._read = function() { * * @param {object} options - Configuration options. * @param {string} options.bucketName - Name of the bucket. - * @param {string} options.keyFilename - Full path to the JSON key downloaded - * from the Google Developers Console. + * @param {string=} options.keyFilename - Full path to the JSON key downloaded + * from the Google Developers Console. Alternatively, you may provide a + * `credentials` object. + * @param {object=} options.credentials - Credentials object, used in place of + * a `keyFilename`. * * @example * var gcloud = require('gcloud'); @@ -117,6 +120,7 @@ function Bucket(options) { } this.bucketName = options.bucketName; this.conn = new conn.Connection({ + credentials: options.credentials, keyFilename: options.keyFilename, scopes: SCOPES }); diff --git a/test/common/connection.js b/test/common/connection.js index 8087774ce16..73e903982f8 100644 --- a/test/common/connection.js +++ b/test/common/connection.js @@ -26,6 +26,7 @@ var connection = require('../../lib/common/connection.js'); describe('Connection', function() { var conn; + var privateKeyFileJson = require('../testdata/privateKeyFile.json'); beforeEach(function() { conn = new connection.Connection({ @@ -34,7 +35,6 @@ describe('Connection', function() { }); it('should use a private key json file', function(done) { - var privateKeyFileJson = require('../testdata/privateKeyFile.json'); conn.fetchServiceAccountToken_ = function(callback) { callback(null); }; @@ -45,6 +45,24 @@ describe('Connection', function() { }); }); + describe('credentials object', function() { + it('should accept and assign a complete credentials object', function() { + var credConnection = new connection.Connection({ + credentials: privateKeyFileJson + }); + assert.deepEqual(credConnection.credentials, privateKeyFileJson); + }); + + it('should reject an incomplete credentials object', function() { + assert.throws(function() { + new connection.Connection({ + credentials: {} + }); + }, /must contain/); + }); + }); + + describe('Token', function() { var tokenNeverExpires = new connection.Token('token', new Date(3000, 0, 0)); var tokenExpired = new connection.Token('token', new Date(2011, 0, 0));