@@ -5,10 +5,11 @@ var
BadRequestError = require('kuzzle-common-objects').Errors.badRequestError,
ResponseObject = require('kuzzle-common-objects').Models.responseObject,
NotFoundError = require('kuzzle-common-objects').Errors.notFoundError,
formatProcessing = require('../core/auth/formatProcessing');
formatProcessing = require('../core/auth/formatProcessing'),
User = require('../core/models/security/user');

function SecurityController (kuzzle) {
var User = require('../core/models/security/user')(kuzzle);


/**
* Get a specific role according to the given id
@@ -183,10 +184,10 @@ function SecurityController (kuzzle) {
return q.reject(new BadRequestError('Missing profile ids'));
}

return kuzzle.repositories.profile.loadMultiFromDatabase(modifiedRequestObject.data.body.ids, modifiedRequestObject.data.body.hydrate);
return kuzzle.repositories.profile.loadMultiFromDatabase(modifiedRequestObject.data.body.ids);
})
.then(profiles => {
profiles = profiles.map(profile => formatProcessing.formatProfileForSerialization(profile, modifiedRequestObject.data.body.hydrate));
profiles = profiles.map(profile => formatProcessing.formatProfileForSerialization(profile));

return kuzzle.pluginsManager.trigger('security:afterMGetProfiles', new ResponseObject(modifiedRequestObject, {hits: profiles, total: profiles.length}));
});
@@ -272,8 +273,7 @@ function SecurityController (kuzzle) {
return kuzzle.repositories.profile.searchProfiles(
roles,
modifiedRequestObject.data.body.from,
modifiedRequestObject.data.body.size,
modifiedRequestObject.data.body.hydrate
modifiedRequestObject.data.body.size
);
})
.then((response) => {
@@ -336,7 +336,7 @@ function SecurityController (kuzzle) {
return q.reject(new NotFoundError(`Profile with id ${modifiedRequestObject.data._id} not found`));
}

return profile.getRights();
return profile.getRights(kuzzle);
})
.then(rights => {
return q(Object.keys(rights).reduce((array, item) => array.concat(rights[item]), []));
@@ -357,7 +357,6 @@ function SecurityController (kuzzle) {
*/
this.getUserRights = function (requestObject) {
var modifiedRequestObject = null;

return kuzzle.pluginsManager.trigger('security:beforeGetUserRights', requestObject)
.then(newRequestObject => {
modifiedRequestObject = newRequestObject;
@@ -373,7 +372,7 @@ function SecurityController (kuzzle) {
return q.reject(new NotFoundError(`User with id ${modifiedRequestObject.data._id} not found`));
}

return user.getRights();
return user.getRights(kuzzle);
})
.then(rights => Object.keys(rights).reduce((array, item) => array.concat(rights[item]), []))
.then(rights => {
@@ -400,8 +399,7 @@ function SecurityController (kuzzle) {
return kuzzle.repositories.user.search(
modifiedRequestObject.data.body.filter || {},
modifiedRequestObject.data.body.from,
modifiedRequestObject.data.body.size,
modifiedRequestObject.data.body.hydrate
modifiedRequestObject.data.body.size
);
})
.then(response => {
@@ -457,25 +455,35 @@ function SecurityController (kuzzle) {
var pojoUser;

modifiedRequestObject = newRequestObject;
console.log('requestObject', requestObject)
console.log('modifiedRequestObject', modifiedRequestObject)

if (!modifiedRequestObject.data.body || !modifiedRequestObject.data.body.profile) {
return q.reject(new BadRequestError('Invalid user object. No profile property found.'));
}

pojoUser = modifiedRequestObject.data.body;

console.log('pojoUser', pojoUser)
if (modifiedRequestObject.data._id !== undefined) {
pojoUser._id = modifiedRequestObject.data._id;
}
else {
pojoUser._id = uuid.v4();
}
console.log('pojoUser', pojoUser)

return kuzzle.repositories.user.hydrate(user, pojoUser);
})
.then(modifiedUser => kuzzle.repositories.user.persist(modifiedUser, { database: {method: 'create'} }))
.then(modifiedUser => {
console.log('modifiedUser', modifiedUser)

return kuzzle.repositories.user.persist(modifiedUser, { database: {method: 'create'} })
})
.then(modifiedUser => formatProcessing.formatUserForSerialization(kuzzle, modifiedUser, true))
.then(serializedUser => kuzzle.pluginsManager.trigger('security:afterCreateUser', new ResponseObject(modifiedRequestObject, serializedUser)));
.then(serializedUser => {
console.log('serializedUser', serializedUser)
return kuzzle.pluginsManager.trigger('security:afterCreateUser', new ResponseObject(modifiedRequestObject, serializedUser))
});
};

/**
@@ -1,5 +1,6 @@
var
q = require('q');
q = require('q'),
_ = require('lodash');

module.exports = {
/**
@@ -9,7 +10,7 @@ module.exports = {
* @returns {Object}
*/
formatRoleForSerialization: function (role) {
var response = {};
/* var response = {};
response = {_id: role._id, _source: {}};
Object.keys(role).forEach((key) => {
@@ -21,7 +22,8 @@ module.exports = {
}
});
return response;
return response;*/
return role;
},

/**
@@ -31,25 +33,28 @@ module.exports = {
* @param {boolean} hydrate
* @returns {Object}
*/
formatProfileForSerialization: function (profile, hydrate) {
formatProfileForSerialization: function (profile) {
var response;
/*
if (!hydrate) {
return profile;
}
if (!hydrate) {
return profile;
}

response = {_id: profile._id, _source: {}};
Object.keys(profile).forEach((key) => {
if (key === 'roles') {
response._source.roles = profile.roles.map((role) => {
return this.formatRoleForSerialization(role);
});
}
else if (key !== '_id') {
response._source[key] = profile[key];
}
});
response = {_id: profile._id, _source: {}};
Object.keys(profile).forEach((key) => {
if (key === 'roles') {
response._source.roles = profile.roles.map((role) => {
return this.formatRoleForSerialization(role);
});
}
else if (key !== '_id') {
response._source[key] = profile[key];
}
});
return response;*/
response = _.assignIn({}, {_id: profile._id, _source: profile});
delete response._source._id;
return response;
},

@@ -61,20 +66,23 @@ module.exports = {
* @param {boolean} hydrate
* @returns {Object}
*/
formatUserForSerialization: function (kuzzle, user, hydrate) {
formatUserForSerialization: function (kuzzle, user) {
return kuzzle.pluginsManager.trigger('security:formatUserForSerialization', user)
.then(triggeredUser => {
if (typeof triggeredUser.profile === 'string') {
/* if (typeof triggeredUser.profile === 'string') {
return kuzzle.repositories.profile.loadProfile(triggeredUser.profile)
.then(profile => {
triggeredUser.profile = profile;
return q(triggeredUser);
});
}

return q(triggeredUser);
}*/
console.log('triggered',triggeredUser)
console.log('user',user)
var response = _.assignIn({}, {_id: triggeredUser._id, _source: triggeredUser})
delete response._source._id;
return q(response);
})
.then(triggeredUser => {
/* .then(triggeredUser => {
var
response = triggeredUser;
@@ -90,6 +98,6 @@ module.exports = {
});
}
return q(response);
});
})*/;
}
};
@@ -58,7 +58,7 @@ function TokenManager (kuzzle) {

if (this.tokenizedConnections[key].expiresAt < now) {
connectionId = this.tokenizedConnections[key].connection.id;
// Send a token expiration notfication to the user
// Send a token expiration notification to the user
if (kuzzle.hotelClerk.customers[connectionId]) {
rooms = Object.keys(kuzzle.hotelClerk.customers[connectionId]);
requestObject = new RequestObject({
@@ -182,8 +182,8 @@ function HotelClerk (kuzzle) {

requestObjectCollection.index = room.index;
requestObjectCollection.collection = room.collection;

context.token.user.profile.isActionAllowed(requestObjectCollection, context, kuzzle)
context.token.user.isActionAllowed(requestObjectCollection, context, kuzzle)
.then(isAllowed => {
if (!isAllowed) {
return callback(null);
@@ -204,6 +204,8 @@ module.exports = function (kuzzle) {
* @returns {Object}
*/
ProfileRepository.prototype.serializeToDatabase = function (profile) {
var result = _.assignIn({}, profile);
/*
var result = {};
Object.keys(profile).forEach(function (key) {
@@ -226,6 +228,7 @@ module.exports = function (kuzzle) {
}
result.roles.push(serializedRole);
});
*/

delete result._id;

@@ -2,8 +2,8 @@ var
_ = require('lodash'),
q = require('q'),
InternalError = require('kuzzle-common-objects').Errors.internalError,
RequestObject = require('kuzzle-common-objects').Models.requestObject,
async = require('async');
RequestObject = require('kuzzle-common-objects').Models.requestObject/*,
async = require('async')*/;

/**
* @param {Kuzzle} kuzzle
@@ -132,6 +132,7 @@ Repository.prototype.loadMultiFromDatabase = function (_ids) {
var object = new this.ObjectConstructor();

//return this.hydrate(object, data);
console.log('object', object)
return _.assignIn(object, document._source, {_id: document._id});
});

@@ -149,10 +150,10 @@ Repository.prototype.loadMultiFromDatabase = function (_ids) {
*
* @returns {promise}
*/
Repository.prototype.search = function (filter, from, size, hydrate) {
Repository.prototype.search = function (filter, from, size/*, hydrate*/) {
var
deferred = q.defer(),
hydratedObjects = [],
/*hydratedObjects = [],*/
requestObject;

requestObject = new RequestObject({
@@ -173,16 +174,13 @@ Repository.prototype.search = function (filter, from, size, hydrate) {
return deferred.resolve({total: 0, hits: []});
}

if (!hydrate) {
return deferred.resolve({total: response.total, hits: response.hits.map((document) => {
return {
_id: document._id,
_source: document._source
};
})});
}
// if (!hydrate) {
return deferred.resolve({total: response.total, hits: response.hits.map((document) => {
return _.assignIn({}, document._source, {_id: document._id});
})});
// }

async.each(response.hits, (document, callback) => {
/* async.each(response.hits, (document, callback) => {
var
object,
data;
@@ -198,7 +196,7 @@ Repository.prototype.search = function (filter, from, size, hydrate) {
});
}, () => {
return deferred.resolve({hits: hydratedObjects, total: response.total});
});
});*/
})
.catch(function (error) {
deferred.reject(error);
@@ -398,7 +396,6 @@ Repository.prototype.persistToCache = function (object, opts) {
if (options.ttl !== undefined) {
ttl = options.ttl;
}

if (ttl === false) {
return this.cacheEngine.set(key, JSON.stringify(this.serializeToCache(object)))
.then(doThen);
@@ -457,7 +454,7 @@ Repository.prototype.expireFromCache = function (object, opts) {
* @returns {Object}
*/
Repository.prototype.serializeToCache = function (object) {
return object;
return _.assign({}, object);
};

/**
@@ -29,7 +29,9 @@ module.exports = function (kuzzle) {
deferred = q.defer(),
keys = [],
buffer = {},
result = [];
result = [],
internalIndexAllowedIds = {},
restrictions = {};

roleKeys.forEach(roleKey => {
if (this.roles[roleKey]) {
@@ -38,6 +40,10 @@ module.exports = function (kuzzle) {
else {
keys.push(roleKey);
}
internalIndexAllowedIds[roleKey._id] = roleKey.allowInternalIndex || false;
if (roleKey.restrictedTo) {
restrictions[roleKey._id] = roleKey.restrictedTo;
}
});

if (keys.length === 0) {
@@ -52,6 +58,10 @@ module.exports = function (kuzzle) {
var promises = [];

roles.forEach(role => {
role.allowInternalIndex = internalIndexAllowedIds[role._id];
if (restrictions[role._id]) {
role.restrictedTo = restrictions[role._id];
}
buffer[role._id] = role;
this.roles[role._id] = role;
});
@@ -128,15 +128,13 @@ module.exports = function (kuzzle) {

TokenRepository.prototype.verifyToken = function (token) {
var
deferred,
deferred = q.defer(),
error;

if (token === null) {
return this.anonymous();
}

deferred = q.defer();

try {
jwt.verify(token, kuzzle.config.jsonWebToken.secret);

@@ -145,19 +143,20 @@ module.exports = function (kuzzle) {
if (userToken === null) {
error = new UnauthorizedError('Invalid token', 401);
deferred.reject(error);
return deferred;
return;
}

console.log('yoyo', userToken)
deferred.resolve(userToken);
})
.catch(function (err) {
.catch(err => {
error = new InternalError('Unknown user');
error.details = err;

deferred.reject(error);
});
}
catch (err) {
console.log('errrrrrrrrrrrrrrrrrrrrrr', err)
if (err instanceof jwt.TokenExpiredError) {
error = new UnauthorizedError('Token expired', 401);
error.details = {
@@ -192,7 +191,6 @@ module.exports = function (kuzzle) {
return q(userToken);
}

// Repository.prototype.hydrate(userToken, data)
q(_.assignIn(userToken, data))
.then(t => {
result = t;
@@ -203,14 +201,14 @@ module.exports = function (kuzzle) {

return kuzzle.repositories.user.load(t.user);
})
.then(function (user) {
.then(user => {
result.user = user;
deferred.resolve(result);
});

return deferred.promise;
};

/*
TokenRepository.prototype.serializeToCache = function (token) {
var result = {};
@@ -222,7 +220,7 @@ module.exports = function (kuzzle) {
result.user = token.user._id;
return result;
};
};*/

TokenRepository.prototype.anonymous = function () {
var
@@ -3,7 +3,7 @@ module.exports = function (kuzzle) {
_ = require('lodash'),
q = require('q'),
uuid = require('node-uuid'),
User = require('../security/user')(kuzzle),
User = require('../security/user'),
Repository = require('./repository'),
InternalError = require('kuzzle-common-objects').Errors.internalError;

@@ -17,25 +17,15 @@ function Profile () {
*/

Profile.prototype.getRoles = function (kuzzle) {
var
deferred = q.defer(),
_roles = [];

if (!this._roles) {
this.roles.forEach(role => {
_roles.push(role);
});

kuzzle.repositories.role.loadRoles(_roles)
return kuzzle.repositories.role.loadRoles(this.roles)
.then(roles => {
this._roles = roles;
deferred.resolve(this._roles);
return q(this._roles);
});
}
else {
deferred.resolve(this._roles);
}
return deferred.promise;

return q(this._roles);
};

/**
@@ -48,7 +38,6 @@ Profile.prototype.getRoles = function (kuzzle) {
Profile.prototype.isActionAllowed = function (requestObject, context, kuzzle) {
var
deferred = q.defer();

if (this.roles === undefined || this.roles.length === 0) {
return q(false);
}
@@ -63,6 +52,9 @@ Profile.prototype.isActionAllowed = function (requestObject, context, kuzzle) {
}, result => {
deferred.resolve(result);
});
})
.catch(error => {
deferred.reject(error);
});

return deferred.promise;
@@ -90,46 +82,48 @@ Profile.prototype.validateDefinition = function () {
*
* @return {Promise}
*/
Profile.prototype.getRights = function() {
Profile.prototype.getRights = function(kuzzle) {
var profileRights = {};

this.roles.forEach(role => {
Object.keys(role.controllers).forEach(controller => {
var restrictedTo = _.cloneDeep(role.restrictedTo);

Object.keys(role.controllers[controller].actions).forEach(action => {
var actionRights = role.controllers[controller].actions[action];

if (restrictedTo === undefined || restrictedTo.length === 0) {
restrictedTo = [{index: '*', collections: ['*']}];
}

restrictedTo.forEach(restriction => {
if (restriction.collections === undefined || restriction.collections.length === 0) {
restriction.collections = ['*'];
}

restriction.collections.forEach(collection => {
var
rightsObject = {},
rightsItem = {
controller: controller,
action: action,
index: restriction.index,
collection: collection
},
rightsKey = md5(JSON.stringify(rightsItem));

rightsItem.value = actionRights;
rightsObject[rightsKey] = rightsItem;
profileRights = _.assignWith(profileRights, rightsObject, mergeRights);
return this.getRoles(kuzzle)
.then(roles => {
roles.forEach(role => {
Object.keys(role.controllers).forEach(controller => {
var restrictedTo = _.cloneDeep(role.restrictedTo);

Object.keys(role.controllers[controller].actions).forEach(action => {
var actionRights = role.controllers[controller].actions[action];

if (restrictedTo === undefined || restrictedTo.length === 0) {
restrictedTo = [{index: '*', collections: ['*']}];
}

restrictedTo.forEach(restriction => {
if (restriction.collections === undefined || restriction.collections.length === 0) {
restriction.collections = ['*'];
}

restriction.collections.forEach(collection => {
var
rightsObject = {},
rightsItem = {
controller: controller,
action: action,
index: restriction.index,
collection: collection
},
rightsKey = md5(JSON.stringify(rightsItem));

rightsItem.value = actionRights;
rightsObject[rightsKey] = rightsItem;
profileRights = _.assignWith(profileRights, rightsObject, mergeRights);
});
});
});
});
});
});
});

return q(profileRights);
})
.then(() => q(profileRights));
};

module.exports = Profile;
@@ -16,6 +16,7 @@ var
function Role () {
this.controllers = {};
this.closures = {};
this.allowInternalIndex = false;
}

function doesIndexExist(index, indexes) {
@@ -250,7 +251,6 @@ function canCreateCollection(index, collection, context, kuzzle) {
*/
function checkRestrictions(requestObject) {
var deferred = q.defer();

// If no restrictions, we allow the action:
if (_.isEmpty(this.restrictedTo)) {
return q(true);
@@ -1,41 +1,39 @@
var
q = require('q');

module.exports = function () {
function User () {
this._id = null;
this.profile = null;
}

function User () {
this._id = null;
this.profile = null;
/**
* @param {Kuzzle} kuzzle
*
* @return {Promise}
*/
User.prototype.getProfile = function (kuzzle) {
if (this._profile === undefined) {
return kuzzle.repositories.profile.loadProfile(this.profile)
.then(profile => {
console.log('profile', profile)
this._profile = profile;
return q(profile);
});
}
return q(this._profile);
};

/**
* @param {Kuzzle} kuzzle
*
* @return {Promise}
*/
User.prototype.getProfile = function (kuzzle) {
if (this._profile === undefined) {
return kuzzle.repositories.profile.loadProfile(this.profile)
.then(profile => {
this._profile = profile;
return q(profile);
});
}
return q(this._profile);
};
/**
* @return {Promise}
*/
User.prototype.getRights = function (kuzzle) {
return this.getProfile(kuzzle)
.then(profile => profile.getRights(kuzzle));
};

/**
* @return {Promise}
*/
User.prototype.getRights = function (kuzzle) {
return this.getProfile(kuzzle)
.then(profile => profile.getRights());
};
User.prototype.isActionAllowed = function (requestObject, context, kuzzle) {
return this.getProfile(kuzzle)
.then(profile => profile.isActionAllowed(requestObject, context, kuzzle));
};

User.prototype.isActionAllowed = function (requestObject, context, kuzzle) {
return this.getProfile(kuzzle)
.then(profile => profile.isActionAllowed(requestObject, context, kuzzle));
};

return User;
};
module.exports = User;
@@ -1,9 +1,11 @@
var
should = require('should'),
_ = require('lodash'),
q = require('q'),
sinon = require('sinon'),
params = require('rc')('kuzzle'),
Kuzzle = require.main.require('lib/api/Kuzzle'),
User = require.main.require('lib/api/core/models/security/user'),
Profile = require.main.require('lib/api/core/models/security/profile'),
Role = require.main.require('lib/api/core/models/security/role'),
RequestObject = require.main.require('kuzzle-common-objects').Models.requestObject,
@@ -13,26 +15,26 @@ var

require('sinon-as-promised')(q.Promise);

describe('Test: admin controller', () => {
describe('Test: admin controller', function () {
var
kuzzle,
sandbox,
index = '%text',
collection = 'unit-test-adminController',
requestObject;

before(() => {
before(function () {
kuzzle = new Kuzzle();

return kuzzle.start(params, {dummy: true});
});

beforeEach(() => {
beforeEach(function () {
sandbox = sinon.sandbox.create();
requestObject = new RequestObject({ controller: 'admin' }, {index, collection}, 'unit-test');
});

afterEach(() => {
afterEach(function () {
sandbox.restore();
});

@@ -57,7 +59,7 @@ describe('Test: admin controller', () => {
});
});

it('should add the new collection to the cache', () => {
it('should add the new collection to the cache', function () {
this.timeout(50);
sandbox.stub(kuzzle.workerListener, 'add').resolves({});
sandbox.spy(kuzzle.indexCache, 'add');
@@ -73,7 +75,7 @@ describe('Test: admin controller', () => {
});
});

it('should return a rejected ResponseObject in case of error', () => {
it('should return a rejected ResponseObject in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});
sandbox.spy(kuzzle.indexCache, 'add');
sandbox.spy(kuzzle.indexCache, 'remove');
@@ -97,7 +99,7 @@ describe('Test: admin controller', () => {
return should(kuzzle.funnel.controllers.admin.getMapping(requestObject)).be.rejected();
});

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.services.list.readEngine, 'getMapping').resolves({});
return kuzzle.funnel.controllers.admin.getMapping(requestObject)
.then(response => {
@@ -141,14 +143,14 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.getStats(requestObject);
});

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.statistics, 'getStats').resolves({});

return kuzzle.funnel.controllers.admin.getStats(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.statistics, 'getStats').rejects({});

return should(kuzzle.funnel.controllers.admin.getStats(requestObject)).be.rejected();
@@ -173,14 +175,14 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.getLastStats(requestObject);
});

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.statistics, 'getLastStats').resolves({});

return kuzzle.funnel.controllers.admin.getLastStats(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.statistics, 'getLastStats').rejects({});

return should(kuzzle.funnel.controllers.admin.getLastStats(requestObject)).be.rejected();
@@ -205,29 +207,29 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.getAllStats(requestObject);
});

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.statistics, 'getAllStats').resolves({});

return kuzzle.funnel.controllers.admin.getAllStats(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.statistics, 'getAllStats').rejects({});

return should(kuzzle.funnel.controllers.admin.getAllStats(requestObject)).be.rejected();
});
});

describe('#truncateCollection', function () {
it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});

return kuzzle.funnel.controllers.admin.truncateCollection(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});

return should(kuzzle.funnel.controllers.admin.truncateCollection(requestObject)).be.rejected();
@@ -254,7 +256,7 @@ describe('Test: admin controller', () => {
describe('#deleteIndexes', function () {
var context = {
token: {
user: {}
user: new User()
}
};

@@ -271,9 +273,13 @@ describe('Test: admin controller', () => {
}
}
};
context.token.user.profile = 'deleteIndex';
role.restrictedTo = [{index: '%text1'},{index: '%text2'}];
profile.roles = [role];
context.token.user.profile = profile;
profile.roles = [{_id: role._id, restrictedTo: role.restrictedTo}];

sandbox.stub(kuzzle.repositories.user, 'load').resolves(context.token.user);
sandbox.stub(kuzzle.repositories.profile, 'loadProfile').resolves(profile);
sandbox.stub(kuzzle.repositories.role, 'loadRoles').resolves([role]);
});

it('should trigger a hook on a deleteIndexes call', done => {
@@ -293,14 +299,14 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.deleteIndexes(requestObject, context);
});

it('should delete only the allowed indexes', () => {
it('should delete only the allowed indexes', function () {
var
deleteIndexRequestObject = new RequestObject({
controller: 'admin',
action: 'deleteIndexes',
body: {indexes: ['%text1', '%text2', '%text3']}
}),
isActionAllowedStub = sandbox.stub(context.token.user.profile, 'isActionAllowed'),
isActionAllowedStub = sandbox.stub(context.token.user, 'isActionAllowed'),
workerListenerStub = request => q({deleted: request.data.body.indexes});

this.timeout(50);
@@ -325,21 +331,21 @@ describe('Test: admin controller', () => {
});
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.services.list.readEngine, 'listIndexes').rejects();
return should(kuzzle.funnel.controllers.admin.deleteIndexes(requestObject, context)).be.rejected();
});
});

describe('#createIndex', function () {
it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});

return kuzzle.funnel.controllers.admin.createIndex(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});

return should(kuzzle.funnel.controllers.admin.createIndex(requestObject)).be.rejected();
@@ -362,7 +368,7 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.createIndex(requestObject);
});

it('should add the new index to the cache', () => {
it('should add the new index to the cache', function () {
this.timeout(50);
sandbox.stub(kuzzle.workerListener, 'add').resolves({});
sandbox.spy(kuzzle.indexCache, 'add');
@@ -380,13 +386,13 @@ describe('Test: admin controller', () => {
});

describe('#deleteIndex', function () {
it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});
return kuzzle.funnel.controllers.admin.deleteIndex(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});

return should(kuzzle.funnel.controllers.admin.deleteIndex(requestObject)).be.rejected();
@@ -409,7 +415,7 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.deleteIndex(requestObject);
});

it('should remove the index from the cache', () => {
it('should remove the index from the cache', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});
sandbox.spy(kuzzle.indexCache, 'add');
sandbox.spy(kuzzle.indexCache, 'remove');
@@ -443,19 +449,19 @@ describe('Test: admin controller', () => {
kuzzle.funnel.controllers.admin.removeRooms(requestObject);
});

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.hotelClerk, 'removeRooms').resolves({});
return kuzzle.funnel.controllers.admin.removeRooms(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.hotelClerk, 'removeRooms').rejects({});

return should(kuzzle.funnel.controllers.admin.removeRooms(requestObject)).be.rejected();
});

it('should fulfill with a response object with partial errors, if any', () => {
it('should fulfill with a response object with partial errors, if any', function () {
sandbox.stub(kuzzle.hotelClerk, 'removeRooms').resolves({partialErrors: ['foo', 'bar']});

return kuzzle.funnel.controllers.admin.removeRooms(requestObject)
@@ -468,14 +474,14 @@ describe('Test: admin controller', () => {
});

describe('#refreshIndex', function () {
it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});

return kuzzle.funnel.controllers.admin.refreshIndex(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it('should reject with a response object in case of error', () => {
it('should reject with a response object in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});

return should(kuzzle.funnel.controllers.admin.refreshIndex(requestObject)).be.rejected();
@@ -494,14 +500,14 @@ describe('Test: admin controller', () => {

describe('#getAutoRefresh', function () {

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
sandbox.stub(kuzzle.workerListener, 'add').resolves({});

return kuzzle.funnel.controllers.admin.getAutoRefresh(requestObject)
.then(response => should(response).be.instanceOf(ResponseObject));
});

it ('should reject in case of error', () => {
it ('should reject in case of error', function () {
sandbox.stub(kuzzle.workerListener, 'add').rejects({});

return should(kuzzle.funnel.controllers.admin.getAutoRefresh(requestObject)).be.rejectedWith();
@@ -519,7 +525,7 @@ describe('Test: admin controller', () => {

describe('#setAutoRefresh', function () {

it('should fulfill with a response object', () => {
it('should fulfill with a response object', function () {
var req = new RequestObject({
index: requestObject.index,
body: { autoRefresh: true }
@@ -531,7 +537,7 @@ describe('Test: admin controller', () => {
.then(response => should(response).be.an.instanceOf(ResponseObject));
});

it('should reject the promise if the autoRefresh value is not set', () => {
it('should reject the promise if the autoRefresh value is not set', function () {
var req = new RequestObject({
index: requestObject.index,
body: {}
@@ -540,7 +546,7 @@ describe('Test: admin controller', () => {
return should(kuzzle.funnel.controllers.admin.setAutoRefresh(req)).be.rejectedWith(BadRequestError);
});

it('should reject the promise if the autoRefresh value is not a boolean', () => {
it('should reject the promise if the autoRefresh value is not a boolean', function () {
var req = new RequestObject({
index: requestObject.index,
body: { autoRefresh: -999 }
@@ -549,7 +555,7 @@ describe('Test: admin controller', () => {
return should(kuzzle.funnel.controllers.admin.setAutoRefresh(req)).be.rejectedWith(BadRequestError);
});

it('should reject the promise in case of error', () => {
it('should reject the promise in case of error', function () {
var req = new RequestObject({
index: requestObject.index,
body: { autoRefresh: false }
@@ -86,16 +86,7 @@ describe('Test the auth controller', function () {
}
return q({
_id: t,
profile: {
_id: t,
roles: [
{
_id: 'role1',
controllers: {},
restrictedTo: []
}
]
}
profile: t
});
};
});
@@ -328,10 +319,9 @@ describe('Test the auth controller', function () {

kuzzle.funnel.controllers.auth.getCurrentUser(rq, token)
.then(response => {
console.log(response.data.body)
should(response.data.body._id).be.exactly('admin');
should(response.data.body._source).not.be.empty().Object();
should(response.data.body._source.profile).not.be.empty().Object();
should(response.data.body._source.profile._id).be.exactly('admin');
should(response.data.body._source.profile).be.exactly('admin');

done();
})
@@ -103,15 +103,15 @@ describe('Test: security controller - profiles', function () {
});

it('should resolve to a responseObject on a mGetProfiles call', () => {
sandbox.stub(kuzzle.repositories.profile, 'loadMultiFromDatabase').resolves([{_id: 'test', _source: {roles: [{_id: 'role'}]}}]);
sandbox.stub(kuzzle.repositories.profile, 'loadMultiFromDatabase').resolves([{_id: 'test', roles: [{_id: 'role'}]}]);
return kuzzle.funnel.controllers.security.mGetProfiles(new RequestObject({
body: {ids: ['test']}
}))
.then(result => {
should(result).be.an.instanceOf(ResponseObject);
should(result.data.body.hits).be.an.Array();
should(result.data.body.hits).not.be.empty();

console.log('result.data.body.hits[0]', result.data.body.hits[0])
should(result.data.body.hits[0]).be.an.Object();
should(result.data.body.hits[0]._source.roles).be.an.Array();
should(result.data.body.hits[0]._source.roles[0]).be.an.Object();
@@ -158,6 +158,7 @@ describe('Test: security controller - profiles', function () {
}))
.then(result => {
var jsonResponse = result.toJson();
console.log('jsonResponse.result.hits[0]', jsonResponse.result.hits[0])
should(result).be.an.instanceOf(ResponseObject);
should(jsonResponse.result.hits).be.an.Array();
should(jsonResponse.result.hits[0]._id).be.exactly('test');
@@ -103,18 +103,18 @@ describe('Test: security controller - users', function () {
});
});

it('should return some unhydrated users when asked', () => {
sandbox.stub(kuzzle.repositories.user, 'search').resolves({hits: [{_id: 'admin', _source: {profile: 'admin'}}]});
return kuzzle.funnel.controllers.security.searchUsers(new RequestObject({
body: { hydrate: false }
}))
.then(response => {
should(response).be.an.instanceOf(ResponseObject);
response.data.body.hits.every(doc => {
should(doc._source.profile).be.a.String();
});
});
});
// it('should return some unhydrated users when asked', () => {
// sandbox.stub(kuzzle.repositories.user, 'search').resolves({hits: [{_id: 'admin', _source: {profile: 'admin'}}]});
// return kuzzle.funnel.controllers.security.searchUsers(new RequestObject({
// body: { hydrate: false }
// }))
// .then(response => {
// should(response).be.an.instanceOf(ResponseObject);
// response.data.body.hits.every(doc => {
// should(doc._source.profile).be.a.String();
// });
// });
// });

it('should reject with a response object in case of error', () => {
sandbox.stub(kuzzle.repositories.user, 'search').rejects();
@@ -150,7 +150,7 @@ describe('Test: security controller - users', function () {
});

describe('#createUser', function () {
it('should return a valid a valid response', () => {
it('should return a valid response', () => {
var mock = sandbox.mock(kuzzle.repositories.user).expects('persist').once().resolves({_id: 'test'});
sandbox.stub(kuzzle.repositories.user, 'hydrate').resolves();

@@ -40,7 +40,7 @@ describe('Test: hotelClerk.listSubscription', function () {
});

it('should return a correct list according to subscribe on filter', function () {
context.token.user.profile.isActionAllowed = sinon.stub().resolves(true);
context.token.user.isActionAllowed = sinon.stub().resolves(true);
kuzzle.hotelClerk.rooms[roomName] = {index, collection, roomId: 'foobar', customers: ['foo']};

return kuzzle.hotelClerk.listSubscriptions(context)
@@ -66,8 +66,8 @@ describe('Test: hotelClerk.listSubscription', function () {
}
};

context.token.user.profile.isActionAllowed = sinon.stub().resolves(true);
context.token.user.profile.isActionAllowed.onSecondCall().resolves(false);
context.token.user.isActionAllowed = sinon.stub().resolves(true);
context.token.user.isActionAllowed.onSecondCall().resolves(false);

return kuzzle.hotelClerk.listSubscriptions(context)
.then(response => {
@@ -297,7 +297,7 @@ describe('Test: repositories/profileRepository', () => {
sandbox.stub(kuzzle.repositories.profile, 'persistToDatabase', profile => q({_id: profile._id}));
sandbox.stub(kuzzle.repositories.role, 'loadRoles', stubs.roleRepository.loadRoles);

testProfile.roles = ['anonymous'];
testProfile.roles = [{_id: 'anonymous'}];

return kuzzle.repositories.profile.validateAndSaveProfile(testProfile)
.then((result) => {
@@ -399,7 +399,16 @@ describe('Test: repositories/repository', () => {

describe('#serializeToCache', () => {
it('should return the same object', () => {
var serialized = repository.serializeToCache(persistedObject);
/*
// these does not work...
should(repository.serializeToCache(persistedObject)).be.exactly(persistedObject);
should(_.isEqual(repository.serializeToCache(persistedObject), persistedObject)).be.true();
*/
should(Object.keys(serialized).length).be.exactly(Object.keys(persistedObject).length);
Object.keys(repository.serializeToCache(persistedObject)).forEach(key => {
should(persistedObject[key]).be.exactly(serialized[key]);
})
});
});

@@ -419,14 +428,14 @@ describe('Test: repositories/repository', () => {
});
});

it('should construct role if hydrate is true', () => {
/* it('should construct role if hydrate is true', () => {
return repository.search({}, 0, 10, true)
.then(response => {
should(response).be.an.Object();
should(response.hits).be.an.Array();
should(response.total).be.exactly(1);
should(response.hits[0].type).be.exactly('testObject');
});
});
});*/
});
});
@@ -18,7 +18,7 @@ var
UnauthorizedError = require.main.require('kuzzle-common-objects').Errors.unauthorizedError,
Profile = require.main.require('lib/api/core/models/security/profile'),
Token = require.main.require('lib/api/core/models/security/token'),
User = require.main.require('lib/api/core/models/security/user')(kuzzle),
User = require.main.require('lib/api/core/models/security/user'),
Role = require.main.require('lib/api/core/models/security/role'),
Repository = require.main.require('lib/api/core/models/repositories/repository'),
TokenRepository = require.main.require('lib/api/core/models/repositories/tokenRepository')(kuzzle),
@@ -63,8 +63,10 @@ beforeEach(function (done) {
anonymous: function () {
var
role = new Role(),
profile = new Profile(),
user = new User();

role._id = 'anonymous'
role.controllers = {
'*': {
actions: {
@@ -74,16 +76,18 @@ beforeEach(function (done) {
};

user._id = -1;
user.profile = new Profile();
user.profile.roles = [role];
user.profile = 'anonymous';
profile.roles = [{_id: role._id}];

return q(user);
},
admin: function () {
var
role = new Role(),
profile = new Profile(),
user = new User();

role._id = 'admin'
role.controllers = {
'*': {
actions: {
@@ -93,8 +97,8 @@ beforeEach(function (done) {
};

user._id = 'admin';
user.profile = new Profile();
user.profile.roles = [role];
user.profile = 'admin';
profile.roles = [{_id: role._id}];

return q(user);
}
@@ -180,6 +184,9 @@ describe('Test: repositories/tokenRepository', function () {

describe('#verifyToken', function () {
it('should reject the promise if the jwt is invalid', function () {
console.log('tokenRepository.verifyToken("invalidToken")', tokenRepository.verifyToken('invalidToken'))
console.log('tokenRepository.verifyToken', tokenRepository.verifyToken)

return should(tokenRepository.verifyToken('invalidToken')).be.rejectedWith(UnauthorizedError, {
details: {
subCode: UnauthorizedError.prototype.subCodes.JsonWebTokenError,
@@ -324,7 +331,7 @@ describe('Test: repositories/tokenRepository', function () {
should(result).not.be.an.instanceOf(Token);
should(result).be.an.Object();
should(result._id).be.exactly(undefined);
should(result.user).be.exactly(-1);
should(result.user._id).be.exactly(-1);

done();
})
@@ -13,7 +13,7 @@ var
NotFoundError = require.main.require('kuzzle-common-objects').Errors.notFoundError,
ResponseObject = require.main.require('kuzzle-common-objects').Models.responseObject,
Profile = require.main.require('lib/api/core/models/security/profile'),
User = require.main.require('lib/api/core/models/security/user')(kuzzle),
User = require.main.require('lib/api/core/models/security/user'),
UserRepository = require.main.require('lib/api/core/models/repositories/userRepository')(kuzzle),
userRepository,
userInvalidProfile;
@@ -68,7 +68,7 @@ describe('Test: security/profileTest', function () {
}
};

profile.roles = ['disallowAllRole'];
profile.roles = [{_id: 'disallowAllRole'}];

sandbox.stub(kuzzle.repositories.role, 'loadRoles', (_roles) => {
var result = [];
@@ -82,7 +82,7 @@ describe('Test: security/profileTest', function () {
.then(isAllowed => {
should(isAllowed).be.false();

profile.roles.push('allowActionRole');
profile.roles.push({_id: 'allowActionRole'});
profile._roles = null;
return profile.isActionAllowed(requestObject, context, kuzzle);
})
@@ -132,7 +132,7 @@ describe('Test: security/profileTest', function () {
};
profile.roles.push(role3);

return profile.getRights()
return profile.getRights(kuzzle)
.then(rights => {
var filteredItem;

@@ -39,7 +39,7 @@ describe('Test: security/userTest', function () {
sandbox.stub(user, 'getProfile').resolves(profile);
sandbox.stub(profile, 'getRights').resolves(profileRights);

return user.getRights()
return user.getRights(kuzzle)
.then(rights => {
should(rights).be.an.Object();
should(rights).be.exactly(profileRights);