Skip to content
30 changes: 4 additions & 26 deletions src/security/Security.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,6 @@ Security.prototype.searchUsers = function (filters, options, cb) {
/**
* Create a new user in Kuzzle.
*
* Takes an optional argument object with the following property:
* - replaceIfExist (boolean, default: false):
* If the same user already exists: throw an error if sets to false.
* Replace the existing user otherwise
*
* @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
Expand All @@ -497,8 +492,7 @@ Security.prototype.searchUsers = function (filters, options, cb) {
Security.prototype.createUser = function (id, content, options, cb) {
var
self = this,
data = {_id: id, body: content},
action = 'createUser';
data = {_id: id, body: content};

if (!id || typeof id !== 'string') {
throw new Error('Security.createUser: cannot create a user without a user ID');
Expand All @@ -509,25 +503,9 @@ Security.prototype.createUser = function (id, content, options, cb) {
options = null;
}

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));
});
}
self.kuzzle.query(self.buildQueryArgs('createUser'), data, null, cb && function (err, res) {
cb(err, err ? undefined : new User(self, res.result._id, res.result._source));
});
};

/**
Expand Down
71 changes: 62 additions & 9 deletions src/security/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ function User(Security, id, content) {
},
updateActionName: {
value: 'updateUser'
},
credentials: {
value: {},
writable: true,
enumerable: true
}
});

Expand All @@ -27,7 +32,7 @@ function User(Security, id, content) {
return Security.kuzzle.bluebird.promisifyAll(this, {
suffix: 'Promise',
filter: function (name, func, target, passes) {
var whitelist = ['save', 'saveRestricted'];
var whitelist = ['create', 'replace', 'saveRestricted', 'update'];

return passes && whitelist.indexOf(name) !== -1;
}
Expand Down Expand Up @@ -57,6 +62,19 @@ User.prototype.setProfiles = function (profileIds) {
return this;
};

/**
* @param {object} credentials
*/
User.prototype.setCredentials = function (credentials) {
if (typeof credentials !== 'object') {
throw new Error('Parameter "credentials" must be a object');
}

this.credentials = credentials;

return this;
};

/**
* Add a profile
* @param {string} profileId - a profile ids string
Expand All @@ -80,17 +98,42 @@ User.prototype.addProfile = function (profileId) {
};

/**
* Saves this user into Kuzzle.
* Creates this user into Kuzzle
*
* If this is a new user, this function will create it in Kuzzle.
* Otherwise, this method will replace the latest version of this user in Kuzzle by the current content
* of this object.
* @param {object|responseCallback} [options] - Optional parameters
* @param {responseCallback} [cb] - Handles the query response
* @returns {User} this
*/
User.prototype.create = function (options, cb) {
var
data = this.creationSerialize(),
self = this;

if (!this.content.profileIds) {
throw new Error('Argument "profileIds" is mandatory in a user. This argument contains an array of profile identifiers.');
}

if (options && cb === undefined && typeof options === 'function') {
cb = options;
options = null;
}

this.kuzzle.query(this.Security.buildQueryArgs('createUser'), data, null, cb && function (err) {
cb(err, err ? undefined : self);
});

return this;
};


/**
* Replaces the latest version of this user in Kuzzle by the current content of this object.
*
* @param {object|responseCallback} [options] - Optional parameters
* @param {responseCallback} [cb] - Handles the query response
* @returns {User} this
*/
User.prototype.save = function (options, cb) {
User.prototype.replace = function (options, cb) {
var
data = this.serialize(),
self = this;
Expand All @@ -104,11 +147,12 @@ User.prototype.save = function (options, cb) {
options = null;
}

self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {
cb(error, error ? undefined : self);

this.kuzzle.query(this.Security.buildQueryArgs('replaceUser'), data, null, cb && function (err) {
cb(err, err ? undefined : self);
});

return self;
return this;
};

/**
Expand Down Expand Up @@ -148,6 +192,15 @@ User.prototype.serialize = function () {
return {_id: this.id, body: this.content};
};

/**
* Serialize this object into a JSON object
*
* @return {object} JSON object representing this User
*/
User.prototype.creationSerialize = function () {
return {_id: this.id, body: {content: this.content, credentials: this.credentials}};
};

/**
* Return the associated profiles IDs
*
Expand Down
36 changes: 4 additions & 32 deletions test/security/kuzzleSecurity/userMethods.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var
should = require('should'),
sinon = require('sinon'),
Kuzzle = require('../../../src/Kuzzle'),
User = require('../../../src/security/User');
User = require('../../../src/security/User'),
sinon = require('sinon');

describe('Security user methods', function () {
var
Expand Down Expand Up @@ -143,13 +143,13 @@ describe('Security user methods', function () {
it('should send the right query to Kuzzle', function (done) {
this.timeout(50);

should(kuzzle.security.createUser('foobar', content, function (err, res) {
should(kuzzle.security.createUser('foobar', {content: content, credentials: {some: 'credentials'}}, function (err, res) {
should(err).be.null();
should(res).be.instanceof(User);
done();
}));
should(kuzzle.query).be.calledOnce();
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {content: content, credentials: {some: 'credentials'}}}, null, sinon.match.func);

kuzzle.query.yield(null, result);
});
Expand All @@ -160,34 +160,6 @@ describe('Security user methods', function () {
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, undefined);
});

it('should construct a replaceUser action if option replaceIfExist is set to true', function () {
kuzzle.security.createUser('foobar', content, {replaceIfExist: true});
should(kuzzle.security.fetchUser).be.calledOnce();
should(kuzzle.security.fetchUser).be.calledWith('foobar', sinon.match.func);

expectedQuery.action = 'replaceUser';
kuzzle.security.fetchUser.yield(null, new User(kuzzle.security, 'foobar'));
should(kuzzle.query).be.calledOnce();
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content});
});

it('should throw an error if replaceIfExist is false but user already exists', function (done) {
this.timeout(50);

kuzzle.security.createUser('foobar', content, {replaceIfExist: false}, function (err, res) {
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();
done();
});
should(kuzzle.security.fetchUser).be.calledOnce();
should(kuzzle.security.fetchUser).be.calledWith('foobar', sinon.match.func);

expectedQuery.action = 'replaceUser';
kuzzle.security.fetchUser.yield(null, new User(kuzzle.security, 'foobar'));
should(kuzzle.query).not.be.called();
});

it('should throw an error if no id provided', function () {
should(function () { kuzzle.security.createUser(null); }).throw(Error);
should(kuzzle.query).not.be.called();
Expand Down
3 changes: 2 additions & 1 deletion test/security/kuzzleUser/constructor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ describe('User constructor', function () {
kuzzleUser = new User(kuzzle.security, 'test', {});

should.exist(kuzzleUser.setProfiles);
should.exist(kuzzleUser.savePromise);
should.exist(kuzzleUser.createPromise);
should.exist(kuzzleUser.replacePromise);
should.exist(kuzzleUser.serialize);
should.exist(kuzzleUser.deletePromise);
});
Expand Down
Loading