Huge performance improvement on roles queries

This commit is contained in:
Florent Vilmart
2016-04-05 20:44:26 -04:00
parent 1bd804693c
commit cbbd66964a
2 changed files with 76 additions and 87 deletions

View File

@@ -114,30 +114,17 @@ Auth.prototype._loadRoles = function() {
this.rolePromise = null;
return Promise.resolve(this.userRoles);
}
var rolesMap = results.reduce((m, r) => {
m.names.push(r.name);
m.ids.push(r.objectId);
return m;
}, {ids: [], names: []});
var roleIDs = results.map(r => r.objectId);
var promises = [Promise.resolve(roleIDs)];
var queriedRoles = {};
for (var role of roleIDs) {
promises.push(this._getAllRoleNamesForId(role, queriedRoles));
}
return Promise.all(promises).then((results) => {
var allIDs = [];
for (var x of results) {
Array.prototype.push.apply(allIDs, x);
}
var restWhere = {
objectId: {
'$in': allIDs
}
};
var query = new RestQuery(this.config, master(this.config),
'_Role', restWhere, {});
return query.execute();
}).then((response) => {
var results = response.results;
this.userRoles = results.map((r) => {
return 'role:' + r.name;
// run the recursive finding
return this._getAllRolesNamesForRoleIds(rolesMap.ids, rolesMap.names)
.then((roleNames) => {
this.userRoles = roleNames.map((r) => {
return 'role:' + r;
});
this.fetchedRoles = true;
this.rolePromise = null;
@@ -146,50 +133,52 @@ Auth.prototype._loadRoles = function() {
});
};
// Given a role object id, get any other roles it is part of
Auth.prototype._getAllRoleNamesForId = function(roleID, queriedRoles = {}) {
// Don't need to requery this role as it is already being queried for.
if (queriedRoles[roleID] != null) {
return Promise.resolve([]);
// Given a list of roleIds, find all the parent roles, returns a promise with all names
Auth.prototype._getAllRolesNamesForRoleIds = function(roleIDs, names = [], queriedRoles = {}) {
let ins = roleIDs.filter((roleID) => {
return queriedRoles[roleID] !== true;
}).map((roleID) => {
// mark as queried
queriedRoles[roleID] = true;
return {
__type: 'Pointer',
className: '_Role',
objectId: roleID
}
});
// all roles are accounted for, return the names
if (ins.length == 0) {
return Promise.resolve([...new Set(names)]);
}
queriedRoles[roleID] = true;
// As per documentation, a Role inherits AnotherRole
// if this Role is in the roles pointer of this AnotherRole
// Let's find all the roles where this role is in a roles relation
var rolePointer = {
__type: 'Pointer',
className: '_Role',
objectId: roleID
};
var restWhere = {
'roles': rolePointer
};
var query = new RestQuery(this.config, master(this.config), '_Role',
restWhere, {});
// Build an OR query across all parentRoles
let restWhere;
if (ins.length == 1) {
restWhere = { 'roles': ins[0] };
} else {
restWhere = { 'roles': { '$in': ins }}
}
let query = new RestQuery(this.config, master(this.config), '_Role', restWhere, {});
return query.execute().then((response) => {
var results = response.results;
// Nothing found
if (!results.length) {
return Promise.resolve([]);
return Promise.resolve(names);
}
var roleIDs = results.map(r => r.objectId);
// we found a list of roles where the roleID
// is referenced in the roles relation,
// Get the roles where those found roles are also
// referenced the same way
var parentRolesPromises = roleIDs.map( (roleId) => {
return this._getAllRoleNamesForId(roleId, queriedRoles);
});
parentRolesPromises.push(Promise.resolve(roleIDs));
return Promise.all(parentRolesPromises);
}).then(function(results){
// Flatten
let roleIDs = results.reduce( (memo, result) => {
return memo.concat(result);
}, []);
return Promise.resolve([...new Set(roleIDs)]);
});
};
// Map the results with all Ids and names
let resultMap = results.reduce((memo, role) => {
memo.names.push(role.name);
memo.ids.push(role.objectId);
return memo;
}, {ids: [], names: []});
// store the new found names
names = names.concat(resultMap.names);
// find the next ones, circular roles will be cut
return this._getAllRolesNamesForRoleIds(resultMap.ids, names, queriedRoles)
}).then((names) => {
return Promise.resolve([...new Set(names)])
})
}
module.exports = {
Auth: Auth,