diff --git a/src/Auth.js b/src/Auth.js new file mode 100644 index 000000000..6615f8174 --- /dev/null +++ b/src/Auth.js @@ -0,0 +1,220 @@ +const User = require('./security/User.js'); + +/** + * Auth controller + * + * @param kuzzle + * @constructor + */ +class Auth { + + /** + * constructor + * @param kuzzle + */ + constructor(kuzzle) { + Object.defineProperty(this, 'kuzzle', { + value: kuzzle + }); + } + + /** + * Checks whether a given jwt token still represents a valid session in Kuzzle. + * + * @param {string} token The jwt token to check + * @return {Promise|*|PromiseLike|Promise} + */ + checkToken(token) { + const + request = { + body: { + token + } + }; + + return this.kuzzle.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}) + .then(res => res.result); + } + + /** + * Create credentials of the specified for the current user. + * + * @param credentials + * @param strategy + * @param options + * @returns {Promise|*|PromiseLike|Promise} + */ + createMyCredentials(strategy, credentials, options) { + return this.kuzzle.query({controller: 'auth', action: 'createMyCredentials'}, { + strategy, + body: credentials + }, options) + .then(res => res.result); + } + + /** + * Check the existence of the specified 's credentials for the current user. + * + * @param strategy + * @returns {Promise|*|PromiseLike|Promise} + */ + credentialsExist(strategy, options) { + return this.kuzzle.query({controller: 'auth', action: 'credentialsExist'}, {strategy}, options) + .then(res => res.result); + } + + /** + * Delete credentials of the specified for the current user. + * + * @param strategy + * @param options + * @returns {Promise|*|PromiseLike|Promise} + */ + deleteMyCredentials(strategy, options) { + return this.kuzzle.query({controller: 'auth', action: 'deleteMyCredentials'}, {strategy}, options) + .then(res => res.result); + } + + /** + * Fetches the current user. + * + * @returns {Promise|*|PromiseLike|Promise} + */ + getCurrentUser() { + return this.kuzzle.query({controller: 'auth', action: 'getCurrentUser'}, {}, undefined) + .then(res => { + return new User(this.kuzzle.security, res.result._id, res.result._source, res.result._meta); + }); + } + + /** + * Get credential information of the specified for the current user. + * + * @param strategy + * @returns {Promise|*|PromiseLike|Promise} + */ + getMyCredentials(strategy, options) { + return this.kuzzle.query({controller: 'auth', action: 'getMyCredentials'}, {strategy}, options) + .then(res => res.result); + } + + /** + * Gets the rights array of the currently logged user. + * + * @param {object} [options] - Optional parameters + * @returns {Promise|*|PromiseLike|Promise} + */ + getMyRights(options) { + return this.kuzzle.query({controller: 'auth', action: 'getMyRights'}, {}, options) + .then(res => res.result.hits); + } + + /** + * Get all the strategies registered in Kuzzle by all auth plugins + * + * @param {object} [options] - Optional parameters + * @returns {Promise|*|PromiseLike|Promise} + */ + getStrategies(options) { + return this.kuzzle.query({controller: 'auth', action: 'getStrategies'}, {}, options) + .then(res => res.result); + } + + /** + * Send login request to kuzzle with credentials + * If login success, store the jwt into kuzzle object + * + * @param strategy + * @param credentials + * @param expiresIn + * @returns {Promise|*|PromiseLike|Promise} + */ + login(strategy, credentials, expiresIn) { + if (!strategy || typeof strategy !== 'string') { + return Promise.reject(new Error('Auth.login: strategy required')); + } + + const + request = { + strategy, + body: {} + }; + + request.body = credentials || {}; + if (expiresIn) { + request.expiresIn = expiresIn; + } + + return this.kuzzle.query({controller: 'auth', action: 'login'}, request, {queuable: false}) + .then(response => { + try { + this.kuzzle.setJwt(response.result.jwt); + this.kuzzle.emit('loginAttempt', {success: true}); + } catch (err) { + return Promise.reject(err); + } + return response.result.jwt; + }) + .catch(err => { + this.kuzzle.emit('loginAttempt', {success: false, error: err.message}); + return new Error(err); + }); + } + + /** + * Send logout request to kuzzle with jwt. + * + * @returns {Promise|*|PromiseLike|Promise} + */ + logout() { + return this.kuzzle.query({controller: 'auth', action: 'logout'}, {}, {queuable: false}) + .then(() => this.kuzzle.unsetJwt()); + } + + /** + * Update credentials of the specified for the current user. + * + * @param strategy + * @param credentals + * @param options + * @returns {Promise|*|PromiseLike|Promise} + */ + updateMyCredentials(strategy, credentials, options) { + return this.kuzzle.query({controller: 'auth', action: 'updateMyCredentials'}, { + strategy, + body: credentials + }, options) + .then(res => res.result); + } + + /** + * Update current user in Kuzzle. + * + * @param {object} content - a plain javascript object representing the user's modification + * @param {object} [options] - (optional) arguments + * @returns {Promise|*|PromiseLike|Promise} + */ + updateSelf(content, options) { + return this.kuzzle.query({controller: 'auth', action: 'updateSelf'}, {body: content}, options) + .then(res => res.result); + } + + /** + * Validate credentials of the specified for the current user. + * + * @param strategy + * @param credentials + * @param options + * @returns {Promise|*|PromiseLike|Promise} + */ + validateMyCredentials(strategy, credentials, options) { + return this.kuzzle.query({controller: 'auth', action: 'validateMyCredentials'}, { + strategy, + body: credentials + }, options) + .then(res => res.result); + } + +} + +module.exports = Auth; \ No newline at end of file diff --git a/src/Kuzzle.js b/src/Kuzzle.js index 9b238140c..78818743a 100644 --- a/src/Kuzzle.js +++ b/src/Kuzzle.js @@ -5,7 +5,7 @@ const Document = require('./Document.js'), Security = require('./security/Security'), MemoryStorage = require('./MemoryStorage'), - User = require('./security/User'), + Auth = require('./Auth.js'), networkWrapper = require('./networkWrapper'); /** @@ -87,7 +87,7 @@ class Kuzzle extends KuzzleEventEmitter { // Forward the subscribe query to the network wrapper Object.defineProperty(this, 'subscribe', { - value: function(room, opts, subscribeCB) { + value: function (room, opts, subscribeCB) { const object = { requestId: uuidv4(), @@ -161,6 +161,14 @@ class Kuzzle extends KuzzleEventEmitter { } }); + /** + * Singletons for Kuzzle API + */ + Object.defineProperty(this, 'auth', { + value: new Auth(this), + enumerable: true + }); + /** * Create an attribute security that embed all methods to manage Role, Profile and User */ @@ -174,12 +182,12 @@ class Kuzzle extends KuzzleEventEmitter { enumerable: true }); - Object.defineProperty(this, 'collections',{ + Object.defineProperty(this, 'collections', { value: {}, writable: true }); - Object.defineProperty(this, 'eventTimeout',{ + Object.defineProperty(this, 'eventTimeout', { value: options && typeof options.eventTimeout === 'number' ? options.eventTimeout : 200 }); @@ -312,10 +320,10 @@ class Kuzzle extends KuzzleEventEmitter { } /** - * Emit an event to all registered listeners - * An event cannot be emitted multiple times before a timeout has been reached. - */ - emit (eventName, ...payload) { + * Emit an event to all registered listeners + * An event cannot be emitted multiple times before a timeout has been reached. + */ + emit(eventName, ...payload) { const now = Date.now(), protectedEvent = this.protectedEvents[eventName]; @@ -335,7 +343,7 @@ class Kuzzle extends KuzzleEventEmitter { * Connects to a Kuzzle instance using the provided host name * @param {function} [cb] Connection callback */ - connect (cb) { + connect(cb) { if (this.network.isReady()) { if (cb) { cb(null, this); @@ -395,26 +403,19 @@ class Kuzzle extends KuzzleEventEmitter { * @param token * @returns {Kuzzle} */ - setJwt (token) { + setJwt(token) { if (typeof token === 'string') { this.jwt = token; } else if (typeof token === 'object') { if (token.result && token.result.jwt && typeof token.result.jwt === 'string') { this.jwt = token.result.jwt; } else { - this.emit('loginAttempt', { - success: false, - error: 'Cannot find a valid JWT in the following object: ' + JSON.stringify(token) - }); - - return this; + throw new Error('Cannot find a valid JWT in the following object: ' + JSON.stringify(token)); } } else { - this.emit('loginAttempt', {success: false, error: 'Invalid token argument: ' + token}); - return this; + throw new Error('Invalid token argument: ' + token); } - this.emit('loginAttempt', {success: true}); return this; } @@ -422,7 +423,7 @@ class Kuzzle extends KuzzleEventEmitter { * Unset the jwt used to query kuzzle * @returns {Kuzzle} */ - unsetJwt () { + unsetJwt() { this.jwt = undefined; return this; } @@ -431,180 +432,10 @@ class Kuzzle extends KuzzleEventEmitter { * Get the jwt used by kuzzle * @returns {Kuzzle} */ - getJwt () { + getJwt() { return this.jwt; } - /** - * Send login request to kuzzle with credentials - * If login success, store the jwt into kuzzle object - * - * @param strategy - * @param credentials - * @param expiresIn - * @param cb - */ - login (strategy, ...args) { - if (!strategy || typeof strategy !== 'string') { - throw new Error('Kuzzle.login: strategy required'); - } - - const - request = { - strategy, - body: {} - }; - - let cb = null; - - // Handle arguments (credentials, expiresIn, cb) - if (args[0]) { - if (typeof args[0] === 'object') { - request.body = args[0]; - } else if (typeof args[0] === 'number' || typeof args[0] === 'string') { - request.expiresIn = args[0]; - } else if (typeof args[0] === 'function') { - cb = args[0]; - } - } - if (args[1]) { - if (typeof args[1] === 'number' || typeof args[1] === 'string') { - request.expiresIn = args[1]; - } else if (typeof args[1] === 'function') { - cb = args[1]; - } - } - if (args[2] && typeof args[2] === 'function') { - cb = args[2]; - } - - this.query({controller: 'auth', action: 'login'}, request, {queuable: false}, (error, response) => { - if (!error) { - if (response.result.jwt) { - this.setJwt(response.result.jwt); - } - - cb && cb(null, response.result); - } - else { - cb && cb(error); - this.emit('loginAttempt', {success: false, error: error.message}); - } - }); - } - - /** - * Create credentials of the specified for the current user. - * - * @param credentials - * @param strategy - * @param options - * @param cb - * @returns {Kuzzle} - */ - createMyCredentials (strategy, credentials, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'createMyCredentials'}, {strategy, body: credentials}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result._source); - } - }); - - return this; - } - - /** - * Delete credentials of the specified for the current user. - * - * @param strategy - * @param options - * @param cb - * @returns {Kuzzle} - */ - deleteMyCredentials (strategy, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'deleteMyCredentials'}, {strategy}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result); - } - }); - - return this; - } - - /** - * Get credential information of the specified for the current user. - * - * @param strategy - * @param options - * @param cb - */ - getMyCredentials (strategy, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'getMyCredentials'}, {strategy}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result); - } - }); - } - - /** - * Update credentials of the specified for the current user. - * - * @param strategy - * @param credentals - * @param options - * @param cb - * @returns {Kuzzle} - */ - updateMyCredentials (strategy, credentials, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'updateMyCredentials'}, {strategy, body: credentials}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result); - } - }); - - return this; - } - - /** - * Validate credentials of the specified for the current user. - * - * @param strategy - * @param credentials - * @param options - * @param cb - */ - validateMyCredentials (strategy, credentials, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'validateMyCredentials'}, {strategy, body: credentials}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result); - } - }); - } - /** * Create a kuzzle index * @@ -613,7 +444,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {responseCallback} cb * @returns {Kuzzle} */ - createIndex (index, options, cb) { + createIndex(index, options, cb) { if (!index) { if (!this.defaultIndex) { throw new Error('Kuzzle.createIndex: index required'); @@ -635,108 +466,6 @@ class Kuzzle extends KuzzleEventEmitter { return this; } - /** - * Send logout request to kuzzle with jwt. - * - * @param cb - * @returns {Kuzzle} - */ - logout (cb) { - const - request = { - action: 'logout', - controller: 'auth', - requestId: uuidv4(), - body: {} - }; - - this.query({controller: 'auth', action: 'logout'}, request, {queuable: false}, error => { - if (typeof cb === 'function') { - cb(error, this); - } - }); - - return this.unsetJwt(); - } - - /** - * Checks whether a given jwt token still represents a valid session in Kuzzle. - * - * @param {string} token The jwt token to check - * @param {function} cb The callback to be called when the response is - * available. The signature is `function(error, response)`. - */ - checkToken (token, cb) { - const - request = { - body: { - token - } - }; - - this.callbackRequired('Kuzzle.checkToken', cb); - - this.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}, (err, res) => { - cb(err, err ? undefined : res.result); - }); - } - - /** - * Fetches the current user. - * - * @param {function} cb The callback to be called when the response is - * available. The signature is `function(error, response)`. - */ - whoAmI (cb) { - this.callbackRequired('Kuzzle.whoAmI', cb); - - this.query({controller: 'auth', action: 'getCurrentUser'}, {}, {}, (err, res) => { - cb(err, err ? undefined : new User(this.security, res.result._id, res.result._source, res.result._meta)); - }); - } - - /** - * Gets the rights array of the currently logged user. - * - * @param {object} [options] - Optional parameters - * @param {function} cb The callback containing the normalized array of rights. - */ - getMyRights (options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.callbackRequired('Kuzzle.getMyRights', cb); - - this.query({controller: 'auth', action:'getMyRights'}, {}, options, (err, res) => { - cb(err, err ? undefined : res.result.hits); - }); - } - - /** - * Update current user in Kuzzle. - * - * @param {object} content - a plain javascript object representing the user's modification - * @param {object} [options] - (optional) arguments - * @param {responseCallback} [cb] - (optional) Handles the query response - * @returns {Kuzzle} this object - */ - updateSelf (content, options, cb) { - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } - - this.query({controller: 'auth', action: 'updateSelf'}, {body: content}, options, (err, res) => { - if (typeof cb === 'function') { - cb(err, err ? undefined : res.result); - } - }); - - return this; - } - /** * Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their * insertion. @@ -744,7 +473,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {string} event - name of the global event to subscribe to * @param {function} listener - callback to invoke each time an event is fired */ - addListener (event, listener) { + addListener(event, listener) { if (this.eventActions.indexOf(event) === -1) { throw new Error(`[${event}] is not a known event. Known events: ${this.eventActions.toString()}`); } @@ -759,7 +488,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional parameters * @param {responseCallback} cb - Handles the query response */ - getAllStatistics (options, cb) { + getAllStatistics(options, cb) { if (!cb && typeof options === 'function') { cb = options; options = null; @@ -767,7 +496,7 @@ class Kuzzle extends KuzzleEventEmitter { this.callbackRequired('Kuzzle.getAllStatistics', cb); - this.query({controller:'server', action: 'getAllStats'}, {}, options, (err, res) => { + this.query({controller: 'server', action: 'getAllStats'}, {}, options, (err, res) => { cb(err, err ? undefined : res.result.hits); }); } @@ -781,7 +510,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional parameters * @param {responseCallback} cb - Handles the query response */ - getStatistics (...args) { + getStatistics(...args) { let startTime, stopTime, @@ -842,7 +571,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {string} [index] - The name of the data index containing the data collection * @returns {Collection} A Collection instance */ - collection (collection, index) { + collection(collection, index) { if (!index) { if (!this.defaultIndex) { throw new Error('Unable to create a new data collection object: no index specified'); @@ -871,7 +600,7 @@ class Kuzzle extends KuzzleEventEmitter { * * @returns {Kuzzle} */ - flushQueue () { + flushQueue() { this.network.flushQueue(); return this; } @@ -883,7 +612,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional parameters * @param {responseCallback} cb - Handles the query response */ - listCollections (...args) { + listCollections(...args) { let index, options, @@ -926,7 +655,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional arguments * @param {responseCallback} cb - Handles the query response */ - listIndexes (options, cb) { + listIndexes(options, cb) { if (!cb && typeof options === 'function') { cb = options; options = null; @@ -942,7 +671,7 @@ class Kuzzle extends KuzzleEventEmitter { /** * Disconnects from Kuzzle and invalidate this instance. */ - disconnect () { + disconnect() { this.network.close(); for (const collection of Object.keys(this.collections)) { @@ -956,7 +685,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional arguments * @param {responseCallback} cb - Handles the query response */ - getServerInfo (options, cb) { + getServerInfo(options, cb) { if (!cb && typeof options === 'function') { cb = options; options = null; @@ -977,7 +706,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {responseCallback} cb - Handles the query response * @returns {Kuzzle} */ - refreshIndex (...args) { + refreshIndex(...args) { let index, options, @@ -1016,7 +745,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} options - Optinal arguments * @param {responseCallback} cb - Handles the query response */ - getAutoRefresh (...args) { + getAutoRefresh(...args) { let index, options, @@ -1056,7 +785,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {responseCallback} cb - Handles the query result * @returns {object} this */ - setAutoRefresh (...args) { + setAutoRefresh(...args) { var index, autoRefresh, @@ -1101,7 +830,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional parameters * @param {responseCallback} cb - Handles the query response */ - now (options, cb) { + now(options, cb) { if (!cb && typeof options === 'function') { cb = options; options = null; @@ -1127,7 +856,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional arguments * @param {responseCallback} [cb] - Handles the query response */ - query (queryArgs, query, options, cb) { + query(queryArgs, query = {}, options = null) { const object = { action: queryArgs.action, @@ -1135,15 +864,6 @@ class Kuzzle extends KuzzleEventEmitter { volatile: this.volatile }; - if (!cb && typeof options === 'function') { - cb = options; - options = null; - } else if (!cb && !options && typeof query === 'function') { - cb = query; - query = {}; - options = null; - } - if (options) { for (const prop of ['refresh', 'from', 'size', 'scroll', 'scrollId']) { if (options[prop] !== undefined) { @@ -1157,10 +877,13 @@ class Kuzzle extends KuzzleEventEmitter { } if (!query || typeof query !== 'object' || Array.isArray(query)) { - throw new Error('Invalid query parameter: ' + query); + return Promise.reject(Error(`Invalid query parameter: ${JSON.stringify(query)}`)); } - Object.assign(object.volatile, query.volatile, {sdkInstanceId: this.network.id, sdkVersion: this.sdkVersion}); + Object.assign(object.volatile, query.volatile, { + sdkInstanceId: this.network.id, + sdkVersion: this.sdkVersion + }); for (const attr of Object.keys(query)) { if (attr !== 'volatile') { @@ -1188,15 +911,14 @@ class Kuzzle extends KuzzleEventEmitter { object.requestId = uuidv4(); } - this.network.query(object, options, cb); - - return this; + return this.network.query(object, options) + .then(response => response.result); } /** * Starts the requests queuing. */ - startQueuing () { + startQueuing() { this.network.startQueuing(); return this; } @@ -1204,7 +926,7 @@ class Kuzzle extends KuzzleEventEmitter { /** * Stops the requests queuing. */ - stopQueuing () { + stopQueuing() { this.network.stopQueuing(); return this; } @@ -1213,14 +935,14 @@ class Kuzzle extends KuzzleEventEmitter { * @DEPRECATED * See Kuzzle.prototype.playQueue(); */ - replayQueue () { + replayQueue() { return this.playQueue(); } /** * Plays the requests queued during offline mode. */ - playQueue () { + playQueue() { this.network.playQueue(); return this; } @@ -1231,7 +953,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param index * @returns this */ - setDefaultIndex (index) { + setDefaultIndex(index) { if (typeof index !== 'string') { throw new Error(`Invalid default index: [${index}] (an index name is expected)`); } diff --git a/src/networkWrapper/protocols/socketio.js b/src/networkWrapper/protocols/socketio.js index 0f13b5ce6..955dbb7d8 100644 --- a/src/networkWrapper/protocols/socketio.js +++ b/src/networkWrapper/protocols/socketio.js @@ -47,6 +47,7 @@ class SocketIO extends RTWrapper { * * @param {string} event * @param {function} callback + * @param {boolean} once */ addListener(event, callback, once = false) { this._addEventWrapper(event, callback, once); diff --git a/src/security/SecurityDocument.js b/src/security/SecurityDocument.js index 03431524e..1c32efe08 100644 --- a/src/security/SecurityDocument.js +++ b/src/security/SecurityDocument.js @@ -1,5 +1,4 @@ function SecurityDocument(Security, id, content, meta) { - if (!id) { throw new Error('A security document must have an id'); } diff --git a/test/Auth/methods.test.js b/test/Auth/methods.test.js new file mode 100644 index 000000000..f9af866e6 --- /dev/null +++ b/test/Auth/methods.test.js @@ -0,0 +1,480 @@ +const + should = require('should'), + KuzzleMock = require('../mocks/kuzzle.mock'), + Auth = require('../../src/Auth.js'), + User = require('../../src/security/User.js'), + Security = require('../../src/security/Security.js'), + sinon = require('sinon'); + +describe('Kuzzle Auth controller', function () { + let + auth, + kuzzle; + + beforeEach(() => { + kuzzle = new KuzzleMock(); + auth = new Auth(kuzzle); + }); + + describe('#checkToken', function () { + const token = 'fakeToken', + expectedQuery = { + controller: 'auth', + action: 'checkToken' + }, + result = { + result: { + valid: true, + state: 'Error message', + expiresAt: 42424242 + } + }; + + it('should call query with the right arguments and return Promise which resolves', () => { + kuzzle.query.resolves(result); + + return auth.checkToken(token) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {body: {token: token}}, {queuable: false}); + should(res).be.exactly(result.result); + }); + }); + }); + + describe('#createMyCredentials', function () { + const credentials = {foo: 'bar'}, + expectedQuery = { + controller: 'auth', + action: 'createMyCredentials' + }, + result = { + result: { + foo: 'bar' + } + }; + + it('should call query with the right arguments and return Promise which resolves an object', () => { + kuzzle.query.resolves(result); + + return auth.createMyCredentials('strategy', credentials) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {body: {foo: 'bar'}, strategy: 'strategy'}, undefined); + should(res).be.exactly(result.result); + }); + }); + }); + + describe('#credentialsExist', function () { + const expectedQuery = { + controller: 'auth', + action: 'credentialsExist' + }, + result = { + result: { + acknowledged: true + } + }; + + it('should call query with the right arguments and return Promise which resolves an object', () => { + kuzzle.query.resolves(result); + + return auth.credentialsExist('strategy') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {strategy: 'strategy'}, undefined); + should(res).be.exactly(result.result); + }); + }); + }); + + describe('#deleteMyCredentials', function () { + const expectedQuery = { + controller: 'auth', + action: 'deleteMyCredentials' + }, + result = { + result: { + acknowledged: true + } + }; + + it('should call query with the right arguments and return Promise which resolves an object', () => { + kuzzle.query.resolves(result); + + return auth.deleteMyCredentials('strategy') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {strategy: 'strategy'}, undefined); + should(res).be.exactly(result.result); + }); + }); + }); + + describe('#getCurrentUser', function () { + const expectedQuery = { + controller: 'auth', + action: 'getCurrentUser' + }, + result = { + result: { + _id: 'foobar', + _source: { + name: { + first: 'John', + last: 'Doe' + }, + profile: { + _id: 'default', + roles: [ + {_id: 'default'} + ] + } + } + } + }; + + it('should call query with the right arguments and return Promise which resolves a user', () => { + kuzzle.query.resolves(result); + const userResponse = new User(new Security(kuzzle), result.result._id, result.result._source, result.result._meta); + + return auth.getCurrentUser() + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {}, undefined); + should(res.id).be.exactly(userResponse.id); + should(res.content).be.exactly(userResponse.content); + }); + }); + }); + + describe('#getCurrentUser', function () { + const expectedQuery = { + controller: 'auth', + action: 'getCurrentUser' + }, + result = { + result: { + _id: 'foobar', + _source: { + name: { + first: 'John', + last: 'Doe' + }, + profile: { + _id: 'default', + roles: [ + {_id: 'default'} + ] + } + } + } + }; + + it('should call query with the right arguments and return Promise which resolves a user', () => { + kuzzle.query.resolves(result); + const userResponse = new User(new Security(kuzzle), result.result._id, result.result._source, result.result._meta); + + return auth.getCurrentUser() + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {}, undefined); + should(res.id).be.exactly(userResponse.id); + should(res.content).be.exactly(userResponse.content); + }); + }); + }); + + describe('#getMyCredentials', function () { + const expectedQuery = { + controller: 'auth', + action: 'getMyCredentials' + }, + result = { + result: { + username: 'foo', + kuid: '42' + } + }; + + it('should call query with the right arguments and return Promise which resolves an object', () => { + kuzzle.query.resolves(result); + + return auth.getMyCredentials('strategy') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {strategy: 'strategy'}, undefined); + should(res).be.exactly(result.result); + }); + }); + }); + + describe('#getMyRights', function () { + const expectedQuery = { + controller: 'auth', + action: 'getMyRights' + }, + result = { + result: { + hits: [ + { + 'controller': 'ctrl_name', + 'action': 'action_name', + 'index': 'index_name', + 'collection': 'collection_name', + 'value': 'allowed|denied|conditional' + } + ] + } + }; + + it('should call query with the right arguments and return Promise which resolves an array', () => { + kuzzle.query.resolves(result); + + return auth.getMyRights() + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {}, undefined); + should(res).be.an.Array().and.eql(result.result.hits); + }); + }); + }); + + describe('#getStrategies', function () { + const expectedQuery = { + controller: 'auth', + action: 'getStrategies' + }, + result = { + result: [ + 'local', + 'facebook' + ] + }; + + it('should call query with the right arguments and return Promise which resolves an array', () => { + kuzzle.query.resolves(result); + + return auth.getStrategies() + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {}, undefined); + should(res).be.an.Array().and.eql(result.result); + }); + }); + }); + + describe('#login', function () { + const expectedQuery = { + controller: 'auth', + action: 'login' + }, + result = { + result: { + jwt: 'jwt' + } + }; + + it('should reject if no strategy is given', () => { + return auth.login().should.be.rejected(); + }); + + it('should reject if query rejects', () => { + kuzzle.query.rejects(new Error('error')); + + return auth.login('strategy') + .catch(() => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.emit).be.calledWith('loginAttempt', {success: false, error: 'error'}); + }); + }); + + it('should call query with right arguments and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {body: {}, strategy: 'strategy'}, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should call query with right arguments and credentials and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy', {username: 'foo'}) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, { + body: {username: 'foo'}, + strategy: 'strategy' + }, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should call query with right arguments and expiresIn as int and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy', null, 42) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, { + body: {}, + expiresIn: 42, + strategy: 'strategy' + }, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should call query with right arguments and expiresIn as string and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy', null, '4h') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, { + body: {}, + expiresIn: '4h', + strategy: 'strategy' + }, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should call query with right arguments and credentials and expiresIn as int and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy', {username: 'foo'}, 42) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, { + body: {username: 'foo'}, + expiresIn: 42, + strategy: 'strategy' + }, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should call query with right arguments and credentials and expiresIn as int and return Promise which resolves a jwt', () => { + kuzzle.query.resolves(result); + + return auth.login('strategy', {username: 'foo'}, '4h') + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, { + body: {username: 'foo'}, + expiresIn: '4h', + strategy: 'strategy' + }, {queuable: false}); + should(res).be.eql(result.result.jwt); + }); + }); + + it('should reject if setJwt fails', function () { + kuzzle.query.resolves(result); + + kuzzle.setJwt = sinon.stub(); + kuzzle.setJwt.throws(new Error('error')); + + return auth.login('strategy', {username: 'foo'}) + .catch(err => { + should(err).be.eql('error'); + should(kuzzle.emit).not.be.called(); + }); + }); + }); + + describe('#logout', function () { + const expectedQuery = { + controller: 'auth', + action: 'logout' + }, + result = {}; + + it('should call query with the right arguments and return Promise which resolves an array', () => { + kuzzle.query.resolves(result); + + return auth.logout() + .then(() => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {}, {queuable: false}); + should(kuzzle.unsetJwt).be.calledOnce(); + }); + }); + }); + + describe('#updateMyCredentials', function () { + const expectedQuery = { + controller: 'auth', + action: 'updateMyCredentials' + }, + result = { + result: { + username: 'foo', + kuid: '42' + } + }; + + it('should call query with the right arguments and return Promise which resolves an object', () => { + kuzzle.query.resolves(result); + + return auth.updateMyCredentials('strategy', {username: 'foo'}) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {strategy: 'strategy', body: {username: 'foo'}}, undefined); + should(res).be.eql(result.result); + }); + }); + }); + + describe('#updateSelf', function () { + const expectedQuery = { + controller: 'auth', + action: 'updateSelf' + }, + result = { + result: { + username: 'foo', + kuid: '42' + } + }; + + it('should call query with the right arguments and return Promise which resolves a user', () => { + kuzzle.query.resolves(result); + + return auth.updateSelf({username: 'foo'}) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {body: {username: 'foo'}}, undefined); + should(res).be.eql(result.result); + }); + }); + }); + + describe('#validateMyCredentials', function () { + const expectedQuery = { + controller: 'auth', + action: 'validateMyCredentials' + }, + result = { + result: true + }; + + it('should call query with the right arguments and return Promise which resolves a boolean', () => { + kuzzle.query.resolves(result); + + return auth.validateMyCredentials('strategy', {username: 'foo'}) + .then(res => { + should(kuzzle.query).be.calledOnce(); + should(kuzzle.query).be.calledWith(expectedQuery, {strategy: 'strategy', body: {username: 'foo'}}, undefined); + should(res).be.eql(result.result); + }); + }); + }); + +}); \ No newline at end of file diff --git a/test/kuzzle/constructor.test.js b/test/kuzzle/constructor.test.js index b1cc8625d..e4c553657 100644 --- a/test/kuzzle/constructor.test.js +++ b/test/kuzzle/constructor.test.js @@ -29,25 +29,18 @@ describe('Kuzzle constructor', function () { var kuzzle = new Kuzzle('somewhere'); should(kuzzle.addListener).be.a.Function(); - should(kuzzle.checkToken).be.a.Function(); should(kuzzle.collection).be.a.Function(); should(kuzzle.connect).be.a.Function(); should(kuzzle.createIndex).be.a.Function(); - should(kuzzle.createMyCredentials).be.a.Function(); - should(kuzzle.deleteMyCredentials).be.a.Function(); should(kuzzle.disconnect).be.a.Function(); should(kuzzle.flushQueue).be.a.Function(); should(kuzzle.getAllStatistics).be.a.Function(); should(kuzzle.getAutoRefresh).be.a.Function(); should(kuzzle.getJwt).be.a.Function(); - should(kuzzle.getMyCredentials).be.a.Function(); - should(kuzzle.getMyRights).be.a.Function(); should(kuzzle.getServerInfo).be.a.Function(); should(kuzzle.getStatistics).be.a.Function(); should(kuzzle.listCollections).be.a.Function(); should(kuzzle.listIndexes).be.a.Function(); - should(kuzzle.login).be.a.Function(); - should(kuzzle.logout).be.a.Function(); should(kuzzle.now).be.a.Function(); should(kuzzle.playQueue).be.a.Function(); should(kuzzle.query).be.a.Function(); @@ -60,10 +53,6 @@ describe('Kuzzle constructor', function () { should(kuzzle.startQueuing).be.a.Function(); should(kuzzle.stopQueuing).be.a.Function(); should(kuzzle.unsetJwt).be.a.Function(); - should(kuzzle.updateMyCredentials).be.a.Function(); - should(kuzzle.updateSelf).be.a.Function(); - should(kuzzle.validateMyCredentials).be.a.Function(); - should(kuzzle.whoAmI).be.a.Function(); }); it('should expose the documented writable properties', function () { @@ -271,25 +260,18 @@ describe('Kuzzle constructor', function () { kuzzle = new Kuzzle('somewhere'); should(kuzzle.addListenerPromise).be.undefined(); - should(kuzzle.checkTokenPromise).be.a.Function(); should(kuzzle.collectionPromise).be.undefined(); should(kuzzle.connectPromise).be.a.Function(); should(kuzzle.createIndexPromise).be.a.Function(); - should(kuzzle.createMyCredentialsPromise).be.a.Function(); - should(kuzzle.deleteMyCredentialsPromise).be.a.Function(); should(kuzzle.disconnectPromise).be.undefined(); should(kuzzle.flushQueuePromise).be.undefined(); should(kuzzle.getAllStatisticsPromise).be.a.Function(); should(kuzzle.getAutoRefreshPromise).be.a.Function(); should(kuzzle.getJwtPromise).be.undefined(); - should(kuzzle.getMyCredentialsPromise).be.a.Function(); - should(kuzzle.getMyRightsPromise).be.a.Function(); should(kuzzle.getServerInfoPromise).be.a.Function(); should(kuzzle.getStatisticsPromise).be.a.Function(); should(kuzzle.listCollectionsPromise).be.a.Function(); should(kuzzle.listIndexesPromise).be.a.Function(); - should(kuzzle.loginPromise).be.a.Function(); - should(kuzzle.logoutPromise).be.a.Function(); should(kuzzle.nowPromise).be.a.Function(); should(kuzzle.playQueuePromise).be.undefined(); should(kuzzle.queryPromise).be.a.Function(); @@ -302,9 +284,5 @@ describe('Kuzzle constructor', function () { should(kuzzle.startQueuingPromise).be.undefined(); should(kuzzle.stopQueuingPromise).be.undefined(); should(kuzzle.unsetJwtPromise).be.undefined(); - should(kuzzle.updateMyCredentialsPromise).be.a.Function(); - should(kuzzle.updateSelfPromise).be.a.Function(); - should(kuzzle.validateMyCredentialsPromise).be.a.Function(); - should(kuzzle.whoAmIPromise).be.a.Function(); }); }); diff --git a/test/kuzzle/login.test.js b/test/kuzzle/login.test.js deleted file mode 100644 index 000648633..000000000 --- a/test/kuzzle/login.test.js +++ /dev/null @@ -1,199 +0,0 @@ -var - should = require('should'), - sinon = require('sinon'), - Kuzzle = require('../../src/Kuzzle'); - -describe('Kuzzle Login', function () { - var - sandbox = sinon.sandbox.create(), - loginCredentials = {username: 'foo', password: 'bar'}, - kuzzle; - - beforeEach(function() { - kuzzle = new Kuzzle('somewhere', {eventTimeout: 0}); - }); - - afterEach(function() { - sandbox.restore(); - }); - - describe('# with callback', function () { - var queryStub; - - beforeEach(function() { - queryStub = sandbox.stub(kuzzle, 'query').callsFake(function(queryArgs, query, options, cb) { - cb(null, {result: {jwt: 'test-toto'}}); - }); - }); - - it('should handle login with only the strategy', function (done) { - kuzzle.login('local', function() { - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {}, strategy: 'local'}, - {queuable: false} - ); - done(); - }); - }); - - it('should handle login with credentials', function (done) { - kuzzle.login('local', loginCredentials, function() { - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {username: 'foo', password: 'bar'}, strategy: 'local'}, - {queuable: false} - ); - done(); - }); - }); - - it('should handle login without credentials and with expiresIn', function (done) { - kuzzle.login('local', '1h', function() { - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {}, strategy: 'local', expiresIn: '1h'}, - {queuable: false} - ); - done(); - }); - }); - - it('should have the token in login callback', function (done) { - kuzzle.login('local', loginCredentials, '1h', function() { - should(kuzzle.jwt).be.exactly('test-toto'); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {username: 'foo', password: 'bar'}, strategy: 'local', expiresIn: '1h'}, - {queuable: false} - ); - done(); - }); - }); - }); - - describe('# without callback', function () { - var queryStub; - - beforeEach(function() { - queryStub = sandbox.stub(kuzzle, 'query'); - }); - - it('should handle login with only the strategy', function () { - kuzzle.login('local'); - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {}, strategy: 'local'}, - {queuable: false} - ); - }); - - it('should handle login with credentials', function () { - kuzzle.login('local', loginCredentials); - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {username: 'foo', password: 'bar'}, strategy: 'local'}, - {queuable: false} - ); - }); - - it('should handle login without credentials and with expiresIn', function () { - kuzzle.login('local', '1h'); - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {}, strategy: 'local', expiresIn: '1h'}, - {queuable: false} - ); - }); - - it('should handle optional arguments correctly', function () { - kuzzle.login('local', loginCredentials, '1h'); - should(queryStub).be.calledOnce(); - should(queryStub.firstCall).be.calledWith( - {controller: 'auth', action: 'login'}, - {body: {username: 'foo', password: 'bar'}, strategy: 'local', expiresIn: '1h'}, - {queuable: false} - ); - }); - }); - - - describe('#Error Login', function () { - it('should throw if called without strategy', function (done) { - should(function () { - kuzzle.login(); - }).throw(Error); - should(function () { - kuzzle.login({username: 'foo', password: 'bar'}, '1h'); - }).throw(Error); - done(); - }); - - it('should send a failed loginAttempt event if logging in fails', function (done) { - sandbox.stub(kuzzle, 'query').callsFake(function(queryArgs, query, options, cb) { - cb({message: 'foobar'}); - }); - - kuzzle.addListener('loginAttempt', function (status) { - should(status.success).be.false(); - should(status.error).be.eql('foobar'); - done(); - }); - - kuzzle.login('local', {}); - }); - - it('should not forward an event if there is no JWT token in the response', function (done) { - var loginAttemptStub = sinon.stub(); - sandbox.stub(kuzzle, 'query').callsFake(function(queryArgs, query, options, cb) { - cb(null, {result: {}}); - }); - - kuzzle.addListener('loginAttempt', loginAttemptStub); - - kuzzle.login('local', {}); - - setTimeout(function () { - should(loginAttemptStub).not.be.called(); - done(); - }); - }); - - it('should give an error if login query fail to the login callback if is set', function (done) { - sandbox.stub(kuzzle, 'query').callsFake(function(queryArgs, query, options, cb) { - cb(new Error()); - }); - - kuzzle.login('local', loginCredentials, '1h', function(error) { - should(error).be.an.instanceOf(Error); - done(); - }); - }); - }); - - describe('#Logout', function () { - it('should have a empty token in logout callback', function () { - var unsetJwt = sinon.spy(kuzzle, 'unsetJwt'); - - kuzzle.logout(); - should(unsetJwt).be.calledOnce(); - }); - - it('should give an error if logout query fail to the logout callback if is set', function (done) { - sandbox.stub(kuzzle, 'query').callsFake(function(queryArgs, query, options, cb) { - cb(new Error()); - }); - - kuzzle.logout(function(error) { - should(error).be.an.instanceOf(Error); - done(); - }); - }); - }); -}); diff --git a/test/kuzzle/methods.test.js b/test/kuzzle/methods.test.js index 4d337bac4..55993ab6d 100644 --- a/test/kuzzle/methods.test.js +++ b/test/kuzzle/methods.test.js @@ -4,15 +4,14 @@ var sinon = require('sinon'), sandbox = sinon.sandbox.create(), Kuzzle = rewire('../../src/Kuzzle'), - Collection = require('../../src/Collection.js'), - User = require('../../src/security/User'); + Collection = require('../../src/Collection.js'); describe('Kuzzle methods', function () { var error, result, kuzzle, - queryStub = function(queryArgs, query, options, cb) { + queryStub = function (queryArgs, query, options, cb) { if (!cb && typeof options === 'function') { cb = options; options = null; @@ -32,79 +31,61 @@ describe('Kuzzle methods', function () { sandbox.restore(); }); - describe('#checkToken', function () { - var token = 'fakeToken-eoijaodmowifnw8h'; - - beforeEach(function() { - sandbox.stub(kuzzle, 'query').callsFake(queryStub); - }); - - it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.checkToken(); }).throw(Error); - should(kuzzle.query).not.be.called(); - should(function () { kuzzle.checkToken(token); }).throw(Error); - should(kuzzle.query).not.be.called(); - }); - - it('should call query with the right arguments', function () { - var - now = Date.now(), - cb = sinon.stub(), - expectedQuery = { - controller: 'auth', - action: 'checkToken' - }; - - result = { - result: { - valid: true, - state: 'Error message', - expiresAt: now + 1000 - } - }; - - kuzzle.checkToken(token,cb); - should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {body: {token: token}}, {queuable: false}); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly(null, result.result); - }); - - it('should execute the callback with an error if an error occurs', function () { - var cb = sinon.stub(); - - error = 'foobar'; - kuzzle.checkToken(token, cb); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly('foobar', undefined); - }); - }); - describe('#collection', function () { it('should throw an error if arguments are not strings', function () { kuzzle.defaultIndex = 'foobar'; - should(function () { kuzzle.collection(undefined); }).throw(/string expected/); - should(function () { kuzzle.collection(undefined, 'foo'); }).throw(/string expected/); - should(function () { kuzzle.collection(null); }).throw(/string expected/); - should(function () { kuzzle.collection(null, 'foo'); }).throw(/string expected/); - should(function () { kuzzle.collection(123); }).throw(/string expected/); - should(function () { kuzzle.collection(123, 'foo'); }).throw(/string expected/); - should(function () { kuzzle.collection('foo', 123); }).throw(/string expected/); - should(function () { kuzzle.collection({foo: 'bar'}); }).throw(/string expected/); - should(function () { kuzzle.collection({foo: 'bar'}, 'foo'); }).throw(/string expected/); - should(function () { kuzzle.collection('foo', {foo: 'bar'}); }).throw(/string expected/); - should(function () { kuzzle.collection(['bar']); }).throw(/string expected/); - should(function () { kuzzle.collection('foo', ['bar']); }).throw(/string expected/); - should(function () { kuzzle.collection(['bar'], 'foo'); }).throw(/string expected/); + should(function () { + kuzzle.collection(undefined); + }).throw(/string expected/); + should(function () { + kuzzle.collection(undefined, 'foo'); + }).throw(/string expected/); + should(function () { + kuzzle.collection(null); + }).throw(/string expected/); + should(function () { + kuzzle.collection(null, 'foo'); + }).throw(/string expected/); + should(function () { + kuzzle.collection(123); + }).throw(/string expected/); + should(function () { + kuzzle.collection(123, 'foo'); + }).throw(/string expected/); + should(function () { + kuzzle.collection('foo', 123); + }).throw(/string expected/); + should(function () { + kuzzle.collection({foo: 'bar'}); + }).throw(/string expected/); + should(function () { + kuzzle.collection({foo: 'bar'}, 'foo'); + }).throw(/string expected/); + should(function () { + kuzzle.collection('foo', {foo: 'bar'}); + }).throw(/string expected/); + should(function () { + kuzzle.collection(['bar']); + }).throw(/string expected/); + should(function () { + kuzzle.collection('foo', ['bar']); + }).throw(/string expected/); + should(function () { + kuzzle.collection(['bar'], 'foo'); + }).throw(/string expected/); }); it('should throw an error if the kuzzle instance has been invalidated', function () { kuzzle.state = 'disconnected'; - should(function () { kuzzle.collection('foo'); }).throw(Error); + should(function () { + kuzzle.collection('foo'); + }).throw(Error); }); it('should throw an error if no index is provided and no default index has been set', function () { - should(function () { kuzzle.collection('foo'); }).throw(/no index specified/); + should(function () { + kuzzle.collection('foo'); + }).throw(/no index specified/); }); it('should create and store the data collection instance', function () { @@ -115,7 +96,7 @@ describe('Kuzzle methods', function () { }); it('should simply pull the collection from the collection history if reinvoked', function () { - kuzzle.collections.foo = { bar: 'qux'}; + kuzzle.collections.foo = {bar: 'qux'}; should(kuzzle.collection('bar', 'foo')).be.a.String().and.be.exactly('qux'); }); @@ -137,7 +118,9 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no index is given and no defaultIndex is set', function () { - should(function () { kuzzle.createIndex(); }).throw('Kuzzle.createIndex: index required'); + should(function () { + kuzzle.createIndex(); + }).throw('Kuzzle.createIndex: index required'); }); it('should send the right query to Kuzzle even without callback', function () { @@ -193,85 +176,6 @@ describe('Kuzzle methods', function () { }); }); - describe('#createMyCredentials', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.createMyCredentials('strategy', {foo: 'bar'}, function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('createMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - doc = {_id: '42'}, - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: {_source: doc}}), - args; - - kuzzle.createMyCredentials('strategy', {foo: 'bar'}, function (err, res) { - should(res).be.exactly(doc); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('createMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - - describe('#deleteMyCredentials', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.deleteMyCredentials('strategy', function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('deleteMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: {acknowledged: true}}), - args; - - kuzzle.deleteMyCredentials('strategy', function (err, res) { - should(res.acknowledged).be.exactly(true); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('deleteMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - describe('#getAllStatistics', function () { var expectedQuery = { controller: 'server', @@ -284,9 +188,13 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.getAllStatistics(); }).throw(Error); + should(function () { + kuzzle.getAllStatistics(); + }).throw(Error); should(kuzzle.query).not.be.called(); - should(function () { kuzzle.getAllStatistics({some: 'options'}); }).throw(Error); + should(function () { + kuzzle.getAllStatistics({some: 'options'}); + }).throw(Error); should(kuzzle.query).not.be.called(); }); @@ -330,11 +238,15 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no index is given and no defaultIndex is set', function () { - should(function () { kuzzle.getAutoRefresh(); }).throw('Kuzzle.getAutoRefresh: index required'); + should(function () { + kuzzle.getAutoRefresh(); + }).throw('Kuzzle.getAutoRefresh: index required'); }); it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.getAutoRefresh('index'); }).throw(Error); + should(function () { + kuzzle.getAutoRefresh('index'); + }).throw(Error); should(kuzzle.query).not.be.called(); }); @@ -359,7 +271,7 @@ describe('Kuzzle methods', function () { it('should send the right query to Kuzzle', function () { var cb = sinon.stub(), - options = { foo: 'bar'}, + options = {foo: 'bar'}, expectedQuery = { controller: 'index', action: 'getAutoRefresh', @@ -390,86 +302,6 @@ describe('Kuzzle methods', function () { }); }); - describe('#getMyCredentials', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.getMyCredentials('strategy', function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('getMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - doc = {_id: '42'}, - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: doc}), - args; - - kuzzle.getMyCredentials('strategy', function (err, res) { - should(res).be.exactly(doc); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('getMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - - describe('#getMyRights', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.getMyRights(function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('getMyRights'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - doc = {_id: '42'}, - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: {hits: [doc]}}), - args; - - kuzzle.getMyRights(function (err, res) { - should(res).be.an.Array().and.containEql(doc); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('getMyRights'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - describe('#getServerInfo', function () { var expectedQuery = { controller: 'server', @@ -478,35 +310,47 @@ describe('Kuzzle methods', function () { beforeEach(function () { sandbox.stub(kuzzle, 'query').callsFake(queryStub); - result = {result: {serverInfo: { - kuzzle: - { version: '0.9.2', - api: { version: '1.0', routes: {} }, - nodeVersion: 'v4.2.1', - memoryUsed: 100020224, - uptime: '161089.628s', - plugins: - { 'kuzzle-plugin-logger': {}, - 'kuzzle-plugin-socketio': {}, - 'kuzzle-plugin-auth-passport-local': {} }, - system: { memory: {}, cpus: {} } }, - services: { - writeEngine: { - type: 'elasticsearch', - api: '1.7', - version: '1.5.2', - lucene: '4.10.4', - status: 'red', - nodes: {}, - spaceUsed: '14.5kb' + result = { + result: { + serverInfo: { + kuzzle: + { + version: '0.9.2', + api: {version: '1.0', routes: {}}, + nodeVersion: 'v4.2.1', + memoryUsed: 100020224, + uptime: '161089.628s', + plugins: + { + 'kuzzle-plugin-logger': {}, + 'kuzzle-plugin-socketio': {}, + 'kuzzle-plugin-auth-passport-local': {} + }, + system: {memory: {}, cpus: {}} + }, + services: { + writeEngine: { + type: 'elasticsearch', + api: '1.7', + version: '1.5.2', + lucene: '4.10.4', + status: 'red', + nodes: {}, + spaceUsed: '14.5kb' + } + } } } - }}}; + }; }); it('should throw an error if no callback is provided', function () { - should(function () {kuzzle.getServerInfo();}).throw(Error); - should(function () {kuzzle.getServerInfo({some: 'options'});}).throw(Error); + should(function () { + kuzzle.getServerInfo(); + }).throw(Error); + should(function () { + kuzzle.getServerInfo({some: 'options'}); + }).throw(Error); should(kuzzle.query).not.be.called(); }); @@ -548,10 +392,18 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.getStatistics(); }).throw(Error); - should(function () { kuzzle.getStatistics(123456); }).throw(Error); - should(function () { kuzzle.getStatistics({}); }).throw(Error); - should(function () { kuzzle.getStatistics(123456, {}); }).throw(Error); + should(function () { + kuzzle.getStatistics(); + }).throw(Error); + should(function () { + kuzzle.getStatistics(123456); + }).throw(Error); + should(function () { + kuzzle.getStatistics({}); + }).throw(Error); + should(function () { + kuzzle.getStatistics(123456, {}); + }).throw(Error); }); it('should call the query function with getLastStats action if no timestamp is given', function () { @@ -598,7 +450,7 @@ describe('Kuzzle methods', function () { kuzzle.getStatistics(123, options, cb); should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123 }, options); + should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123}, options); should(cb).be.calledOnce(); should(cb).be.calledWithExactly(null, hits); }); @@ -620,7 +472,7 @@ describe('Kuzzle methods', function () { kuzzle.getStatistics(123, 456, options, cb); should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123, stopTime: 456 }, options); + should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123, stopTime: 456}, options); should(cb).be.calledOnce(); should(cb).be.calledWithExactly(null, hits); }); @@ -642,7 +494,7 @@ describe('Kuzzle methods', function () { kuzzle.getStatistics(123, 456, options, cb); should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123, stopTime: 456 }, options); + should(kuzzle.query).be.calledWith(expectedQuery, {startTime: 123, stopTime: 456}, options); should(cb).be.calledOnce(); should(cb).be.calledWithExactly(null, hits); }); @@ -671,21 +523,29 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no callback has been provided', function () { - should(function () { kuzzle.listCollections('foo'); }).throw(Error); - should(function () { kuzzle.listCollections('foo', {}); }).throw(Error); + should(function () { + kuzzle.listCollections('foo'); + }).throw(Error); + should(function () { + kuzzle.listCollections('foo', {}); + }).throw(Error); should(kuzzle.query).not.be.called(); }); it('should throw an error if no index has been provided', function () { - should(function () {kuzzle.listCollections(sinon.stub());}).throw(Error); - should(function () {kuzzle.listCollections({}, sinon.stub());}).throw(Error); + should(function () { + kuzzle.listCollections(sinon.stub()); + }).throw(Error); + should(function () { + kuzzle.listCollections({}, sinon.stub()); + }).throw(Error); should(kuzzle.query).not.be.called(); }); it('should call the query function with the right arguments', function () { var cb = sinon.stub(); - result = { result: {collections: {stored: ['foo', 'bar', 'baz'], realtime: ['qux'] } } }; + result = {result: {collections: {stored: ['foo', 'bar', 'baz'], realtime: ['qux']}}}; kuzzle.listCollections('foo', cb); should(kuzzle.query).be.calledOnce(); @@ -732,10 +592,14 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.listIndexes(); }).throw(Error); + should(function () { + kuzzle.listIndexes(); + }).throw(Error); should(kuzzle.query).not.be.called(); - should(function () {kuzzle.listIndexes({some: 'options'});}).throw(Error); + should(function () { + kuzzle.listIndexes({some: 'options'}); + }).throw(Error); should(kuzzle.query).not.be.called(); }); @@ -782,9 +646,13 @@ describe('Kuzzle methods', function () { }); it('should throw an error if called without a callback', function () { - should(function () { kuzzle.now(); }).throw(Error); + should(function () { + kuzzle.now(); + }).throw(Error); should(kuzzle.query).not.be.called(); - should(function () { kuzzle.now({}); }).throw(Error); + should(function () { + kuzzle.now({}); + }).throw(Error); should(kuzzle.query).not.be.called(); }); @@ -818,7 +686,7 @@ describe('Kuzzle methods', function () { }); describe('#refreshIndex', function () { - beforeEach(function() { + beforeEach(function () { sandbox.stub(kuzzle, 'query').callsFake(queryStub); result = { result: { @@ -832,7 +700,9 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no index is given and no defaultIndex is set', function () { - should(function () {kuzzle.refreshIndex();}).throw('Kuzzle.refreshIndex: index required'); + should(function () { + kuzzle.refreshIndex(); + }).throw('Kuzzle.refreshIndex: index required'); }); it('should send the right query to Kuzzle even without callback', function () { @@ -896,7 +766,9 @@ describe('Kuzzle methods', function () { }); it('should throw an error if no index is given', function () { - should(function () { kuzzle.setAutoRefresh(); }).throw('Kuzzle.setAutoRefresh: index required'); + should(function () { + kuzzle.setAutoRefresh(); + }).throw('Kuzzle.setAutoRefresh: index required'); }); it('should throw an error is now autorefresh value is given', function () { @@ -936,7 +808,7 @@ describe('Kuzzle methods', function () { it('should send the right query to Kuzzle', function () { var cb = sinon.stub(), - options = { foo: 'bar'}, + options = {foo: 'bar'}, expectedQuery = { controller: 'index', action: 'setAutoRefresh', @@ -962,16 +834,30 @@ describe('Kuzzle methods', function () { describe('#setDefaultIndex', function () { it('should throw an error if the provided index is not a string', function () { - should((function () {kuzzle.setDefaultIndex();})).throw(); - should((function () {kuzzle.setDefaultIndex({});})).throw(); - should((function () {kuzzle.setDefaultIndex([]);})).throw(); - should((function () {kuzzle.setDefaultIndex(123);})).throw(); - should((function () {kuzzle.setDefaultIndex(null);})).throw(); - should((function () {kuzzle.setDefaultIndex(undefined);})).throw(); + should((function () { + kuzzle.setDefaultIndex(); + })).throw(); + should((function () { + kuzzle.setDefaultIndex({}); + })).throw(); + should((function () { + kuzzle.setDefaultIndex([]); + })).throw(); + should((function () { + kuzzle.setDefaultIndex(123); + })).throw(); + should((function () { + kuzzle.setDefaultIndex(null); + })).throw(); + should((function () { + kuzzle.setDefaultIndex(undefined); + })).throw(); }); it('should throw an error if the provided index is an empty string', function () { - should((function () {kuzzle.setDefaultIndex('');})).throw(); + should((function () { + kuzzle.setDefaultIndex(''); + })).throw(); }); it('should set the default index in all other cases', function () { @@ -981,43 +867,34 @@ describe('Kuzzle methods', function () { }); describe('#setJwt', function () { - var loginAttemptStub = sinon.stub(); - - beforeEach(function () { - loginAttemptStub.reset(); - kuzzle.addListener('loginAttempt', loginAttemptStub); - }); - it('should set the token when provided with a string argument', function () { kuzzle.setJwt('foobar'); should(kuzzle.jwt).be.eql('foobar'); - should(loginAttemptStub).be.calledOnce(); - should(loginAttemptStub).be.calledWith({success: true}); }); it('should set the token when provided with a kuzzle response argument', function () { - kuzzle.setJwt({result:{jwt: 'foobar'}}); + kuzzle.setJwt({result: {jwt: 'foobar'}}); should(kuzzle.jwt).be.eql('foobar'); - should(loginAttemptStub).be.calledOnce(); - should(loginAttemptStub).be.calledWith({success: true}); }); - it('should send an "attempt failed" event if provided with an invalid argument type', function () { - kuzzle.setJwt(); - - should(kuzzle.jwt).be.undefined(); - should(loginAttemptStub).be.calledOnce(); - should(loginAttemptStub).be.calledWith({ error: 'Invalid token argument: undefined', success: false }); + it('should throw if provided with an invalid argument type', function (done) { + try { + kuzzle.setJwt(); + } catch (e) { + should(e.message).be.eql('Invalid token argument: undefined'); + done(); + } }); - it('should send an "attempt failed" event if the provided kuzzle response does not contain a token', function () { - kuzzle.setJwt({foo: 'bar'}); - - should(kuzzle.jwt).be.undefined(); - should(loginAttemptStub).be.calledOnce(); - should(loginAttemptStub).be.calledWith({ error: 'Cannot find a valid JWT in the following object: {"foo":"bar"}', success: false }); + it('should throw if the provided kuzzle response does not contain a token', function (done) { + try { + kuzzle.setJwt({foo: 'bar'}); + } catch (e) { + should(e.message).be.eql('Cannot find a valid JWT in the following object: {"foo":"bar"}'); + done(); + } }); }); @@ -1029,184 +906,4 @@ describe('Kuzzle methods', function () { }); }); - describe('#updateMyCredentials', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.updateMyCredentials('strategy', {username: 'foo'}, function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('updateMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - doc = {username: 'foo'}, - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: doc}), - args; - - kuzzle.updateMyCredentials('strategy', doc, function (err, res) { - should(res).be.exactly(doc); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('updateMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - - describe('#updateSelf', function () { - var expectedQuery = { - action: 'updateSelf', - controller: 'auth' - }; - - beforeEach(function () { - sandbox.stub(kuzzle, 'query').callsFake(queryStub); - result = { - result: { - _id: 'foobar', - _source: { - name: { - first: 'John', - last: 'Doe' - } - } - } - }; - }); - - it('should send the right query to Kuzzle even without callback', function () { - kuzzle.updateSelf({foo: 'bar'}); - should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {body: {foo: 'bar'}}); - }); - - it('should send the right query to Kuzzle', function () { - var cb = sinon.stub(); - - kuzzle.updateSelf({foo: 'bar'}, cb); - should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {body: {foo: 'bar'}}); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly(null, result.result); - - }); - - it('should execute the callback with an error if an error occurs', function () { - var cb = sinon.stub(); - - error = 'foobar'; - kuzzle.updateSelf({foo: 'bar'}, cb); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly('foobar', undefined); - }); - }); - - describe('#validateMyCredentials', function() { - it('should trigger callback with an error', function (done) { - var - cberror = {message: 'i am an error'}, - spy = sandbox.stub(kuzzle, 'query').yields(cberror), - args; - - kuzzle.validateMyCredentials('strategy', {username: 'foo'}, function (err) { - should(err).be.exactly(cberror); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('validateMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - - it('should call query with right arguments', function (done) { - var - doc = {username: 'foo'}, - spy = sandbox.stub(kuzzle, 'query').yields(null, {result: true}), - args; - - kuzzle.validateMyCredentials('strategy', doc, function (err, res) { - should(res).be.exactly(true); - args = spy.firstCall.args; - - should(spy).be.calledOnce(); - - should(args[0].controller).be.exactly('auth'); - should(args[0].action).be.exactly('validateMyCredentials'); - should(args[2]).be.exactly(null); - done(); - }); - }); - }); - - describe('#whoAmI', function () { - beforeEach(function() { - sandbox.stub(kuzzle, 'query').callsFake(queryStub); - result = { - result: { - _id: 'foobar', - _source: { - name: { - first: 'John', - last: 'Doe' - }, - profile: { - _id: 'default', - roles: [ - {_id: 'default'} - ] - } - } - } - }; - }); - - it('should throw an error if no callback is provided', function () { - should(function () { kuzzle.whoAmI(); }).throw(Error); - should(kuzzle.query).not.be.called(); - }); - - it('should call query with the right arguments', function () { - var - cb = sinon.stub(), - user = new User(kuzzle.security, 'foobar', result.result._source), - expectedQuery = { - controller: 'auth', - action: 'getCurrentUser' - }; - - kuzzle.whoAmI(cb); - should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {}, {}); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly(null, user); - }); - - it('should execute the callback with an error if an error occurs', function () { - var cb = sinon.stub(); - - error = 'foobar'; - kuzzle.whoAmI(cb); - should(cb).be.calledOnce(); - should(cb).be.calledWithExactly('foobar', undefined); - }); - }); }); diff --git a/test/kuzzle/query.test.js b/test/kuzzle/query.test.js index ad7de2ff4..ace68b60d 100644 --- a/test/kuzzle/query.test.js +++ b/test/kuzzle/query.test.js @@ -19,12 +19,13 @@ describe('Kuzzle query management', function () { beforeEach(function () { Kuzzle = proxyquire('../../src/Kuzzle', { - './networkWrapper': function(protocol, host, options) { + './networkWrapper': function (protocol, host, options) { return new NetworkWrapperMock(host, options); } }); kuzzle = new Kuzzle('foo'); + kuzzle.network.query.resolves({result: {}}); }); it('should generate a valid request object with no "options" argument and no callback', function () { @@ -32,11 +33,11 @@ describe('Kuzzle query management', function () { should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWith({ action: 'action', - body: { some: 'query' }, + body: {some: 'query'}, collection: 'collection', controller: 'controller', index: 'index', - volatile: { sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion }, + volatile: {sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion}, requestId: sinon.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i) }); }); @@ -46,44 +47,40 @@ describe('Kuzzle query management', function () { should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWith({ action: 'action', - body: { some: 'query' }, + body: {some: 'query'}, collection: 'collection', controller: 'controller', index: 'index', - volatile: { sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion }, + volatile: {sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion}, requestId: sinon.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i) }); }); it('should manage arguments properly if no options are provided', function () { - var cb = sinon.stub(); - - kuzzle.query(queryArgs, queryBody, cb); + kuzzle.query(queryArgs, queryBody); should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWith({ action: 'action', - body: { some: 'query' }, + body: {some: 'query'}, collection: 'collection', controller: 'controller', index: 'index', - volatile: { sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion }, + volatile: {sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion}, requestId: sinon.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i) - }, null, sinon.match(function(f) {return f === cb;})); + }); }); it('should manage arguments properly if empty query and no options are provided', function () { - var cb = sinon.stub(); - - kuzzle.query(queryArgs, cb); + kuzzle.query(queryArgs); should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWith({ action: 'action', collection: 'collection', controller: 'controller', index: 'index', - volatile: { sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion }, + volatile: {sdkInstanceId: kuzzle.network.id, sdkVersion: kuzzle.sdkVersion}, requestId: sinon.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i) - }, null, sinon.match(function(f) {return f === cb;})); + }); }); it('should not define optional members if none was provided', function () { @@ -92,10 +89,10 @@ describe('Kuzzle query management', function () { should(kuzzle.network.query).be.calledWithMatch({index: undefined}); }); - it('should invoke the callback with an error if no query is provided', function () { - should(function () { kuzzle.query(queryArgs, ['foo', 'bar']); }).throw(Error); - should(function () { kuzzle.query(queryArgs); }).throw(Error); - should(function () { kuzzle.query(queryArgs, 'foobar'); }).throw(Error); + it('should reject if no query is provided', function () { + should(kuzzle.query(queryArgs, ['foo', 'bar'])).be.rejected(); + should(kuzzle.query(queryArgs)).be.rejected(); + should(kuzzle.query(queryArgs, 'foobar')).be.rejected(); }); it('should handle options "volatile" properly', function () { @@ -117,7 +114,7 @@ describe('Kuzzle query management', function () { baz: ['foo', 'bar', 'qux'] }; - kuzzle.query(queryArgs, { body: { some: 'query'}, volatile: {foo: 'foo'}}, {volatile: volatile}); + kuzzle.query(queryArgs, {body: {some: 'query'}, volatile: {foo: 'foo'}}, {volatile: volatile}); should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWithMatch({volatile: {foo: 'foo', baz: volatile.baz}}); }); @@ -153,7 +150,7 @@ describe('Kuzzle query management', function () { }); it('should not generate a new request ID if one is already defined', function () { - kuzzle.query(queryArgs, { body: { some: 'query'}, requestId: 'foobar'}); + kuzzle.query(queryArgs, {body: {some: 'query'}, requestId: 'foobar'}); should(kuzzle.network.query).be.calledOnce(); should(kuzzle.network.query).be.calledWithMatch({requestId: 'foobar'}); }); diff --git a/test/mocks/kuzzle.mock.js b/test/mocks/kuzzle.mock.js index bb50e69c5..8c820c0e6 100644 --- a/test/mocks/kuzzle.mock.js +++ b/test/mocks/kuzzle.mock.js @@ -1,6 +1,7 @@ var NetworkWrapperMock = require('./networkWrapper.mock'), - sinon = require('sinon'); + sinon = require('sinon'), + Security = require('../../src/security/Security.js'); /** * @param err @@ -12,6 +13,9 @@ function KuzzleMock () { this.query = sinon.stub(); this.subscribe = sinon.stub(); this.unsubscribe = sinon.stub(); + this.security = new Security(this); + this.setJwt = sinon.stub(); + this.unsetJwt = sinon.stub(); this.callbackRequired = function (errorMessagePrefix, callback) { if (!callback || typeof callback !== 'function') { diff --git a/test/security/kuzzleSecurity/rightsMethods.test.js b/test/security/kuzzleSecurity/rightsMethods.test.js index 828052aaf..11c48f8f9 100644 --- a/test/security/kuzzleSecurity/rightsMethods.test.js +++ b/test/security/kuzzleSecurity/rightsMethods.test.js @@ -132,68 +132,6 @@ describe('Security user rights methods', function () { }); }); - describe('#getMyRights', function () { - beforeEach(function () { - result = { result: { hits: exampleRights } }; - expectedQuery = { - action: 'getMyRights', - controller: 'auth' - }; - }); - - it('should send the right query to Kuzzle', function (done) { - this.timeout(50); - - kuzzle.getMyRights(function (err, res) { - should(err).be.null(); - should(res).be.exactly(exampleRights); - done(); - }); - - should(kuzzle.query).be.calledOnce(); - should(kuzzle.query).be.calledWith(expectedQuery, {}, null, sinon.match.func); - - kuzzle.query.yield(null, result); - }); - - it('should throw if called with no callback', function () { - should(function () {kuzzle.getMyRights();}).throw(Error); - should(kuzzle.query).not.be.called(); - }); - - it('should call the callback with an error if one occurs', function (done) { - this.timeout(50); - - kuzzle.getMyRights(function (err, res) { - should(err).be.exactly('foobar'); - should(res).be.undefined(); - done(); - }); - - kuzzle.query.yield('foobar'); - }); - - it('should call callback with an array containing rights (if not empty)', function (done) { - this.timeout(50); - - kuzzle.getMyRights(function (err, res) { - should(err).be.exactly(null); - should(res).be.an.instanceOf(Array); - - should(res[0]).have.ownProperty('controller'); - should(res[0]).have.ownProperty('action'); - should(res[0]).have.ownProperty('index'); - should(res[0]).have.ownProperty('collection'); - should(res[0]).have.ownProperty('value'); - should(res[0].value).be.oneOf('allowed', 'denied', 'conditional'); - - done(); - }); - - kuzzle.query.yield(null, result); - }); - }); - describe('#isActionAllowed', function () { it('should return "allowed" to ("read", "get")', function() { should(kuzzle.security.isActionAllowed(exampleRights, 'read', 'get')) diff --git a/webpack.config.js b/webpack.config.js index 974929142..ee420134e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -31,6 +31,7 @@ module.exports = { include: [ path.resolve(__dirname, './src/networkWrapper/protocols/'), path.resolve(__dirname, './src/Kuzzle.js'), + path.resolve(__dirname, './src/Auth.js'), path.resolve(__dirname, './src/Room.js'), path.resolve(__dirname, './src/eventEmitter/'), path.resolve(__dirname, './src/SearchResult.js')