diff --git a/src/security/Security.js b/src/security/Security.js index f54c08126..e606c0b77 100644 --- a/src/security/Security.js +++ b/src/security/Security.js @@ -509,11 +509,50 @@ Security.prototype.createUser = function (id, content, options, cb) { options = null; } - if (options) { - action = options.replaceIfExist ? 'createOrReplaceUser' : 'createUser'; + if (options && options.hasOwnProperty('replaceIfExist')) { + self.fetchUser(id, function (fetchError, fetchResult) { + if (fetchResult instanceof User) { + if (options.replaceIfExist !== true) { + return cb(new Error('Security.createUser: User was found and shouldn\'t be replaced')); + } + action = 'replaceUser'; + } + + self.kuzzle.query(self.buildQueryArgs(action), data, null, cb && function (err, res) { + cb(err, err ? undefined : new User(self, res.result._id, res.result._source)); + }); + }); + } + else { + self.kuzzle.query(self.buildQueryArgs(action), data, null, cb && function (err, res) { + cb(err, err ? undefined : new User(self, res.result._id, res.result._source)); + }); + } +}; + +/** + * Replace an user in Kuzzle. + * + * @param {string} id - user identifier + * @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids + * @param {object|responseCallback} [options] - (optional) arguments + * @param {responseCallback} [cb] - (optional) Handles the query response + */ +Security.prototype.replaceUser = function (id, content, options, cb) { + var + self = this, + data = {_id: id, body: content}; + + if (!id || typeof id !== 'string') { + throw new Error('Security.replaceUser: cannot replace a user without a user ID'); + } + + if (!cb && typeof options === 'function') { + cb = options; + options = null; } - self.kuzzle.query(this.buildQueryArgs(action), data, null, cb && function (err, res) { + self.kuzzle.query(this.buildQueryArgs('replaceUser'), data, options, cb && function (err, res) { cb(err, err ? undefined : new User(self, res.result._id, res.result._source)); }); }; diff --git a/test/security/kuzzleSecurity/userMethods.test.js b/test/security/kuzzleSecurity/userMethods.test.js index d23bccb09..d62a171e7 100644 --- a/test/security/kuzzleSecurity/userMethods.test.js +++ b/test/security/kuzzleSecurity/userMethods.test.js @@ -1,5 +1,6 @@ var should = require('should'), + sinon = require('sinon'), Kuzzle = require('../../../src/Kuzzle'), User = require('../../../src/security/User'); @@ -223,26 +224,103 @@ describe('Security user methods', function () { done(); }); - it('should construct a createOrReplaceUser action if option replaceIfExist is set to true', function (done) { - expectedQuery.body = result.result._source; + it('should construct a replaceUser action if option replaceIfExist is set to true', function (done) { + var spy; + + expectedQuery.body = [{}, result.result._source]; expectedQuery._id = result.result._id; - expectedQuery.action = 'createOrReplaceUser'; + + kuzzle.query = function (args, query, options, cb) { + should(args.controller).be.exactly(expectedQuery.controller); + + if (expectedQuery.options) { + should(options).match(expectedQuery.options); + } + + if (expectedQuery.body) { + if (!query.body) { + query.body = {}; + } + + should(expectedQuery.body).containEql(query.body); + } else { + should(query.body).be.undefined(); + } + + if (expectedQuery._id) { + should(query._id).be.exactly(expectedQuery._id); + } + + if (cb) { + if (error) { + return cb(error); + } + + cb(error, result); + } + }; + spy = sinon.spy(kuzzle, 'query'); should(kuzzle.security.createUser(result.result._id, result.result._source, {replaceIfExist: true}, function (err, res) { + should(spy).be.calledTwice(); + + should(spy.getCall(0).args[0].action).be.exactly('getUser'); + should(spy.getCall(0).args[1]).deepEqual({_id: 'foobar', body: {}}); + + should(spy.getCall(1).args[0].action).be.exactly('replaceUser'); + should(spy.getCall(1).args[1]).deepEqual({_id: 'foobar', body: {profileIds: ['myProfile']}}); + should(err).be.null(); should(res).be.instanceof(User); done(); })); }); - it('should construct a createUser action if option replaceIfExist is set to false', function (done) { + it('should throw an error if replaceIfExist is false but user already exists', function (done) { expectedQuery.body = result.result._source; expectedQuery._id = result.result._id; - expectedQuery.action = 'createUser'; + + kuzzle.query = function (args, query, options, cb) { + should(args.controller).be.exactly(expectedQuery.controller); + + if (expectedQuery.options) { + should(options).match(expectedQuery.options); + } + + if (expectedQuery.body) { + if (!query.body) { + query.body = {}; + } + + should(expectedQuery.body).containEql(query.body); + } else { + should(query.body).be.undefined(); + } + + if (expectedQuery._id) { + should(query._id).be.exactly(expectedQuery._id); + } + + if (cb) { + if (error) { + return cb(error); + } + + cb(error, result); + } + }; + spy = sinon.spy(kuzzle, 'query'); should(kuzzle.security.createUser(result.result._id, result.result._source, {replaceIfExist: false}, function (err, res) { - should(err).be.null(); - should(res).be.instanceof(User); + should(err).be.Object().with.property('message'); + should(err.message).be.exactly('Security.createUser: User was found and shouldn\'t be replaced'); + should(res).be.Undefined(); + + should(spy).be.calledOnce(); + + should(spy.getCall(0).args[0].action).be.exactly('getUser'); + should(spy.getCall(0).args[1]).deepEqual({_id: 'foobar', body: {}}); + done(); })); }); @@ -316,6 +394,43 @@ describe('Security user methods', function () { }); }); + describe('#replaceUser', function () { + beforeEach(function () { + kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); + kuzzle.query = queryStub; + error = null; + result = { result: {_id: 'foobar', _index: '%kuzzle', _type: 'users', _source: {profileIds: ['foobar']} } }; + expectedQuery = { + action: 'replaceUser', + controller: 'security' + }; + }); + + it('should send the right query to Kuzzle', function(done) { + expectedQuery._id = 'foobar'; + expectedQuery.body = {'profileIds': ['foobar']}; + + should(kuzzle.security.replaceUser(expectedQuery._id, expectedQuery.body, function (err, res) { + should(err).be.null(); + should(res).be.instanceOf(User); + should(res).containDeep(new User(kuzzle.security, result.result._id, result.result._source)); + done(); + })); + }); + + it('should send the right query to Kuzzle even without callback', function (done) { + expectedQuery.body = {'foo': 'bar'}; + expectedQuery._id = result.result._id; + + kuzzle.security.replaceUser(result.result._id, {'foo': 'bar'}); + done(); + }); + + it('should throw an error if no id is provided', function () { + should(function () { kuzzle.security.replaceUser(null, {'foo': 'bar'}); }).throw(Error); + }); + }); + describe('#updateUser', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'});