diff --git a/CHANGELOG.md b/CHANGELOG.md index bda724e..7ae45fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.5 + +* Added support for setting authentication database via the `authSource` string. + ## 0.8.4 * Migration files other than `.js` and `.coffee` **will be skipped**, along with dotfiles diff --git a/README.md b/README.md index 994e3b5..b404eec 100644 --- a/README.md +++ b/README.md @@ -73,13 +73,14 @@ from the current directory (include it as your project's dependency). The configuration object can have the following keys: -* `url` — full MongoDB connection url (_optional_, when used the rest of the connection params (`host`, `port`, `db`, `user`, `password`, `replicaset`) are ignored), +* `url` — full MongoDB connection url (_optional_, when used the rest of the connection params (`host`, `port`, `db`, `user`, `password`, `replicaset`, `authDatabase`) are ignored), * `host` — MongoDB host (_optional_ when using `url` or `replicaset`, **required** otherwise), * `port` _[optional]_ — MongoDB port, * `db` — MongoDB database name, * `ssl` _[optional]_ - boolean, if `true`, `'?ssl=true'` is added to the MongoDB URL, * `user` _[optional]_ — MongoDB user name when authentication is required, * `password` _[optional]_ — MongoDB password when authentication is required, +* `authDatabase` _[optional]_ - MongoDB database to authenticate the user against, * `collection` _[optional]_ — The name of the MongoDB collection to track already ran migrations, **defaults to `_migrations`**, * `directory` — the directory (path relative to the current folder) to store migration files in and read them from, used when running from the command-line or when using `runFromDir`, * `timeout` _[optional]_ — time in milliseconds after which migration should fail if `done()` is not called (use 0 to disable timeout) diff --git a/lib/url-builder.js b/lib/url-builder.js index 92f0797..9e823d4 100644 --- a/lib/url-builder.js +++ b/lib/url-builder.js @@ -45,11 +45,14 @@ } params = []; if (replicaset) { - params.push('replicaSet=' + replicaset.name); + params.push("replicaSet=" + replicaset.name); } if (config.ssl) { params.push('ssl=true'); } + if (config.authDatabase) { + params.push("authSource=" + config.authDatabase); + } if (params.length > 0) { s += '?' + params.join('&'); } diff --git a/lib/utils.js b/lib/utils.js index 19b8609..25e4c1d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -61,6 +61,9 @@ if (config.password && !config.user) { throw new Error('`password` provided but `user` is not'); } + if (config.authDatabase && !config.user) { + throw new Error('`authDatabase` provided but `user` is not'); + } }; exports.normalizeConfig = function(config) { diff --git a/src/url-builder.coffee b/src/url-builder.coffee index 57a71e8..e4b8225 100644 --- a/src/url-builder.coffee +++ b/src/url-builder.coffee @@ -40,11 +40,14 @@ module.exports = params = [] if replicaset - params.push 'replicaSet=' + replicaset.name + params.push "replicaSet=#{replicaset.name}" if config.ssl params.push 'ssl=true' + if config.authDatabase + params.push "authSource=#{config.authDatabase}" + if params.length > 0 s += '?' + params.join('&') diff --git a/src/utils.coffee b/src/utils.coffee index b5f1215..54fd4bf 100644 --- a/src/utils.coffee +++ b/src/utils.coffee @@ -50,6 +50,9 @@ validateConnSettings = (config) -> if config.password and not config.user throw new Error('`password` provided but `user` is not') + if config.authDatabase and not config.user + throw new Error('`authDatabase` provided but `user` is not') + exports.normalizeConfig = (config) -> if not (_.isObject(config) and not _.isArray(config)) throw new Error('`config` is not provided or is not an object') diff --git a/test/url-builder.coffee b/test/url-builder.coffee index 3c2396e..a7e5d64 100644 --- a/test/url-builder.coffee +++ b/test/url-builder.coffee @@ -21,9 +21,8 @@ describe 'Url Builder', -> collection: '_migrations' connString = urlBuilder.buildMongoConnString config - connString.should.be.equal 'mongodb://' + config.user + ':' + - config.password + '@' + config.host + ':' + config.port + - '/' + config.db + connString.should.be.equal "mongodb://#{config.user}:#{config.password}@" + + "#{config.host}:#{config.port}/#{config.db}" done() it 'builds a single node url with ssl', (done) -> @@ -37,9 +36,23 @@ describe 'Url Builder', -> ssl: true connString = urlBuilder.buildMongoConnString config - connString.should.be.equal 'mongodb://' + config.user + ':' + - config.password + '@' + config.host + ':' + config.port + - '/' + config.db + '?ssl=true' + connString.should.be.equal "mongodb://#{config.user}:#{config.password}@" + + "#{config.host}:#{config.port}/#{config.db}?ssl=true" + done() + + it 'builds a single node url with an authDatabase', (done) -> + config = + user: 'someuser' + password: 'somepass' + host: 'abcde', + port: 27111 + db: '_mm' + collection: '_migrations', + authDatabase: 'admin' + + connString = urlBuilder.buildMongoConnString config + connString.should.be.equal "mongodb://#{config.user}:#{config.password}@" + + "#{config.host}:#{config.port}/#{config.db}?authSource=#{config.authDatabase}" done() it 'builds a replicaset url with two replicas', (done) -> @@ -62,12 +75,10 @@ describe 'Url Builder', -> collection: '_migrations' connString = urlBuilder.buildMongoConnString config - connString.should.be.equal 'mongodb://' + config.user + ':' + - config.password + '@' + - config.replicaset.members[0].host + ':' + config.replicaset.members[0].port + - ',' + - config.replicaset.members[1].host + ':' + config.replicaset.members[1].port + - '/' + config.db + '?replicaSet=' + config.replicaset.name + connString.should.be.equal "mongodb://#{config.user}:#{config.password}@" + + "#{config.replicaset.members[0].host}:#{config.replicaset.members[0].port}," + + "#{config.replicaset.members[1].host}:#{config.replicaset.members[1].port}/" + + "#{config.db}?replicaSet=#{config.replicaset.name}" done() it 'builds a replicaset url with three replicas', (done) -> @@ -94,12 +105,9 @@ describe 'Url Builder', -> collection: '_migrations' connString = urlBuilder.buildMongoConnString config - connString.should.be.equal 'mongodb://' + config.user + ':' + - config.password + '@' + - config.replicaset.members[0].host + ':' + config.replicaset.members[0].port + - ',' + - config.replicaset.members[1].host + ':' + config.replicaset.members[1].port + - ',' + - config.replicaset.members[2].host + ':' + config.replicaset.members[2].port + - '/' + config.db + '?replicaSet=' + config.replicaset.name + connString.should.be.equal "mongodb://#{config.user}:#{config.password}@" + + "#{config.replicaset.members[0].host}:#{config.replicaset.members[0].port}," + + "#{config.replicaset.members[1].host}:#{config.replicaset.members[1].port}," + + "#{config.replicaset.members[2].host}:#{config.replicaset.members[2].port}/" + + "#{config.db}?replicaSet=#{config.replicaset.name}" done() diff --git a/test/util.coffee b/test/util.coffee index c6eb881..fac177d 100644 --- a/test/util.coffee +++ b/test/util.coffee @@ -154,3 +154,11 @@ describe 'Utils', -> password: 'very secret password' }).should.throw('`password` provided but `user` is not') done() + + it 'should throw with authDatabase but without username', (done) -> + normalizeConfig.bind(null, { + host: 'localhost', + db: '_mm', + authDatabase: 'admin' + }).should.throw('`authDatabase` provided but `user` is not') + done()