Skip to content

Commit 44845db

Browse files
authored
Merge pull request #215 from kuzzleio/21-adapt-replace
Restructure User to be able to store both content and credentials
2 parents ac4058a + f19f5dc commit 44845db

File tree

5 files changed

+160
-92
lines changed

5 files changed

+160
-92
lines changed

src/security/Security.js

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,6 @@ Security.prototype.searchUsers = function (filters, options, cb) {
484484
/**
485485
* Create a new user in Kuzzle.
486486
*
487-
* Takes an optional argument object with the following property:
488-
* - replaceIfExist (boolean, default: false):
489-
* If the same user already exists: throw an error if sets to false.
490-
* Replace the existing user otherwise
491-
*
492487
* @param {string} id - user identifier
493488
* @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids
494489
* @param {object|responseCallback} [options] - (optional) arguments
@@ -497,8 +492,7 @@ Security.prototype.searchUsers = function (filters, options, cb) {
497492
Security.prototype.createUser = function (id, content, options, cb) {
498493
var
499494
self = this,
500-
data = {_id: id, body: content},
501-
action = 'createUser';
495+
data = {_id: id, body: content};
502496

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

512-
if (options && options.hasOwnProperty('replaceIfExist')) {
513-
self.fetchUser(id, function (fetchError, fetchResult) {
514-
if (fetchResult instanceof User) {
515-
if (options.replaceIfExist !== true) {
516-
return cb(new Error('Security.createUser: User was found and shouldn\'t be replaced'));
517-
}
518-
action = 'replaceUser';
519-
}
520-
521-
self.kuzzle.query(self.buildQueryArgs(action), data, null, cb && function (err, res) {
522-
cb(err, err ? undefined : new User(self, res.result._id, res.result._source));
523-
});
524-
});
525-
}
526-
else {
527-
self.kuzzle.query(self.buildQueryArgs(action), data, null, cb && function (err, res) {
528-
cb(err, err ? undefined : new User(self, res.result._id, res.result._source));
529-
});
530-
}
506+
self.kuzzle.query(self.buildQueryArgs('createUser'), data, null, cb && function (err, res) {
507+
cb(err, err ? undefined : new User(self, res.result._id, res.result._source));
508+
});
531509
};
532510

533511
/**

src/security/User.js

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ function User(Security, id, content) {
1919
},
2020
updateActionName: {
2121
value: 'updateUser'
22+
},
23+
credentials: {
24+
value: {},
25+
writable: true,
26+
enumerable: true
2227
}
2328
});
2429

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

3237
return passes && whitelist.indexOf(name) !== -1;
3338
}
@@ -57,6 +62,19 @@ User.prototype.setProfiles = function (profileIds) {
5762
return this;
5863
};
5964

65+
/**
66+
* @param {object} credentials
67+
*/
68+
User.prototype.setCredentials = function (credentials) {
69+
if (typeof credentials !== 'object') {
70+
throw new Error('Parameter "credentials" must be a object');
71+
}
72+
73+
this.credentials = credentials;
74+
75+
return this;
76+
};
77+
6078
/**
6179
* Add a profile
6280
* @param {string} profileId - a profile ids string
@@ -80,17 +98,42 @@ User.prototype.addProfile = function (profileId) {
8098
};
8199

82100
/**
83-
* Saves this user into Kuzzle.
101+
* Creates this user into Kuzzle
84102
*
85-
* If this is a new user, this function will create it in Kuzzle.
86-
* Otherwise, this method will replace the latest version of this user in Kuzzle by the current content
87-
* of this object.
103+
* @param {object|responseCallback} [options] - Optional parameters
104+
* @param {responseCallback} [cb] - Handles the query response
105+
* @returns {User} this
106+
*/
107+
User.prototype.create = function (options, cb) {
108+
var
109+
data = this.creationSerialize(),
110+
self = this;
111+
112+
if (!this.content.profileIds) {
113+
throw new Error('Argument "profileIds" is mandatory in a user. This argument contains an array of profile identifiers.');
114+
}
115+
116+
if (options && cb === undefined && typeof options === 'function') {
117+
cb = options;
118+
options = null;
119+
}
120+
121+
this.kuzzle.query(this.Security.buildQueryArgs('createUser'), data, null, cb && function (err) {
122+
cb(err, err ? undefined : self);
123+
});
124+
125+
return this;
126+
};
127+
128+
129+
/**
130+
* Replaces the latest version of this user in Kuzzle by the current content of this object.
88131
*
89132
* @param {object|responseCallback} [options] - Optional parameters
90133
* @param {responseCallback} [cb] - Handles the query response
91134
* @returns {User} this
92135
*/
93-
User.prototype.save = function (options, cb) {
136+
User.prototype.replace = function (options, cb) {
94137
var
95138
data = this.serialize(),
96139
self = this;
@@ -104,11 +147,12 @@ User.prototype.save = function (options, cb) {
104147
options = null;
105148
}
106149

107-
self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {
108-
cb(error, error ? undefined : self);
150+
151+
this.kuzzle.query(this.Security.buildQueryArgs('replaceUser'), data, null, cb && function (err) {
152+
cb(err, err ? undefined : self);
109153
});
110154

111-
return self;
155+
return this;
112156
};
113157

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

195+
/**
196+
* Serialize this object into a JSON object
197+
*
198+
* @return {object} JSON object representing this User
199+
*/
200+
User.prototype.creationSerialize = function () {
201+
return {_id: this.id, body: {content: this.content, credentials: this.credentials}};
202+
};
203+
151204
/**
152205
* Return the associated profiles IDs
153206
*

test/security/kuzzleSecurity/userMethods.test.js

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
var
22
should = require('should'),
3-
sinon = require('sinon'),
43
Kuzzle = require('../../../src/Kuzzle'),
5-
User = require('../../../src/security/User');
4+
User = require('../../../src/security/User'),
5+
sinon = require('sinon');
66

77
describe('Security user methods', function () {
88
var
@@ -143,13 +143,13 @@ describe('Security user methods', function () {
143143
it('should send the right query to Kuzzle', function (done) {
144144
this.timeout(50);
145145

146-
should(kuzzle.security.createUser('foobar', content, function (err, res) {
146+
should(kuzzle.security.createUser('foobar', {content: content, credentials: {some: 'credentials'}}, function (err, res) {
147147
should(err).be.null();
148148
should(res).be.instanceof(User);
149149
done();
150150
}));
151151
should(kuzzle.query).be.calledOnce();
152-
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
152+
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {content: content, credentials: {some: 'credentials'}}}, null, sinon.match.func);
153153

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

163-
it('should construct a replaceUser action if option replaceIfExist is set to true', function () {
164-
kuzzle.security.createUser('foobar', content, {replaceIfExist: true});
165-
should(kuzzle.security.fetchUser).be.calledOnce();
166-
should(kuzzle.security.fetchUser).be.calledWith('foobar', sinon.match.func);
167-
168-
expectedQuery.action = 'replaceUser';
169-
kuzzle.security.fetchUser.yield(null, new User(kuzzle.security, 'foobar'));
170-
should(kuzzle.query).be.calledOnce();
171-
should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content});
172-
});
173-
174-
it('should throw an error if replaceIfExist is false but user already exists', function (done) {
175-
this.timeout(50);
176-
177-
kuzzle.security.createUser('foobar', content, {replaceIfExist: false}, function (err, res) {
178-
should(err).be.Object().with.property('message');
179-
should(err.message).be.exactly('Security.createUser: User was found and shouldn\'t be replaced');
180-
should(res).be.Undefined();
181-
done();
182-
});
183-
should(kuzzle.security.fetchUser).be.calledOnce();
184-
should(kuzzle.security.fetchUser).be.calledWith('foobar', sinon.match.func);
185-
186-
expectedQuery.action = 'replaceUser';
187-
kuzzle.security.fetchUser.yield(null, new User(kuzzle.security, 'foobar'));
188-
should(kuzzle.query).not.be.called();
189-
});
190-
191163
it('should throw an error if no id provided', function () {
192164
should(function () { kuzzle.security.createUser(null); }).throw(Error);
193165
should(kuzzle.query).not.be.called();

test/security/kuzzleUser/constructor.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ describe('User constructor', function () {
3131
kuzzleUser = new User(kuzzle.security, 'test', {});
3232

3333
should.exist(kuzzleUser.setProfiles);
34-
should.exist(kuzzleUser.savePromise);
34+
should.exist(kuzzleUser.createPromise);
35+
should.exist(kuzzleUser.replacePromise);
3536
should.exist(kuzzleUser.serialize);
3637
should.exist(kuzzleUser.deletePromise);
3738
});

0 commit comments

Comments
 (0)