Skip to content

Commit 00d0d3e

Browse files
committed
Merge pull request #841 from ParsePlatform/flovilmart.Roles
Fix reversed roles lookup
2 parents 3fb6a60 + 17bc79b commit 00d0d3e

File tree

2 files changed

+76
-19
lines changed

2 files changed

+76
-19
lines changed

spec/ParseRole.spec.js

+65-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
"use strict";
22

33
// Roles are not accessible without the master key, so they are not intended
44
// for use by clients. We can manually test them using the master key.
@@ -64,26 +64,30 @@ describe('Parse Role testing', () => {
6464

6565
var rolesNames = ["FooRole", "BarRole", "BazRole"];
6666

67-
var createRole = function(name, parent, user) {
67+
var createRole = function(name, sibling, user) {
6868
var role = new Parse.Role(name, new Parse.ACL());
6969
if (user) {
7070
var users = role.relation('users');
7171
users.add(user);
7272
}
73-
if (parent) {
74-
role.relation('roles').add(parent);
73+
if (sibling) {
74+
role.relation('roles').add(sibling);
7575
}
7676
return role.save({}, { useMasterKey: true });
7777
}
7878
var roleIds = {};
7979
createTestUser().then( (user) => {
80-
81-
return createRole(rolesNames[0], null, null).then( (aRole) => {
80+
// Put the user on the 1st role
81+
return createRole(rolesNames[0], null, user).then( (aRole) => {
8282
roleIds[aRole.get("name")] = aRole.id;
83+
// set the 1st role as a sibling of the second
84+
// user will should have 2 role now
8385
return createRole(rolesNames[1], aRole, null);
8486
}).then( (anotherRole) => {
8587
roleIds[anotherRole.get("name")] = anotherRole.id;
86-
return createRole(rolesNames[2], anotherRole, user);
88+
// set this role as a sibling of the last
89+
// the user should now have 3 roles
90+
return createRole(rolesNames[2], anotherRole, null);
8791
}).then( (lastRole) => {
8892
roleIds[lastRole.get("name")] = lastRole.id;
8993
var auth = new Auth({ config: new Config("test"), isMaster: true, user: user });
@@ -118,6 +122,60 @@ describe('Parse Role testing', () => {
118122
});
119123
});
120124
});
125+
126+
it("Should properly resolve roles", (done) => {
127+
let admin = new Parse.Role("Admin", new Parse.ACL());
128+
let moderator = new Parse.Role("Moderator", new Parse.ACL());
129+
let superModerator = new Parse.Role("SuperModerator", new Parse.ACL());
130+
let contentManager = new Parse.Role('ContentManager', new Parse.ACL());
131+
let superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL());
132+
Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}).then(() => {
133+
contentManager.getRoles().add([moderator, superContentManager]);
134+
moderator.getRoles().add([admin, superModerator]);
135+
superContentManager.getRoles().add(superModerator);
136+
return Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true});
137+
}).then(() => {
138+
var auth = new Auth({ config: new Config("test"), isMaster: true });
139+
// For each role, fetch their sibling, what they inherit
140+
// return with result and roleId for later comparison
141+
let promises = [admin, moderator, contentManager, superModerator].map((role) => {
142+
return auth._getAllRoleNamesForId(role.id).then((result) => {
143+
return Parse.Promise.as({
144+
id: role.id,
145+
name: role.get('name'),
146+
roleIds: result
147+
});
148+
})
149+
});
150+
151+
return Parse.Promise.when(promises);
152+
}).then((results) => {
153+
results.forEach((result) => {
154+
let id = result.id;
155+
let roleIds = result.roleIds;
156+
if (id == admin.id) {
157+
expect(roleIds.length).toBe(2);
158+
expect(roleIds.indexOf(moderator.id)).not.toBe(-1);
159+
expect(roleIds.indexOf(contentManager.id)).not.toBe(-1);
160+
} else if (id == moderator.id) {
161+
expect(roleIds.length).toBe(1);
162+
expect(roleIds.indexOf(contentManager.id)).toBe(0);
163+
} else if (id == contentManager.id) {
164+
expect(roleIds.length).toBe(0);
165+
} else if (id == superModerator.id) {
166+
expect(roleIds.length).toBe(3);
167+
expect(roleIds.indexOf(moderator.id)).not.toBe(-1);
168+
expect(roleIds.indexOf(contentManager.id)).not.toBe(-1);
169+
expect(roleIds.indexOf(superContentManager.id)).not.toBe(-1);
170+
}
171+
});
172+
done();
173+
}).fail((err) => {
174+
console.error(err);
175+
done();
176+
})
177+
178+
});
121179

122180
});
123181

src/Auth.js

+11-12
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,18 @@ Auth.prototype._loadRoles = function() {
139139
};
140140

141141
// Given a role object id, get any other roles it is part of
142-
// TODO: Make recursive to support role nesting beyond 1 level deep
143142
Auth.prototype._getAllRoleNamesForId = function(roleID) {
143+
144+
// As per documentation, a Role inherits AnotherRole
145+
// if this Role is in the roles pointer of this AnotherRole
146+
// Let's find all the roles where this role is in a roles relation
144147
var rolePointer = {
145148
__type: 'Pointer',
146149
className: '_Role',
147150
objectId: roleID
148151
};
149152
var restWhere = {
150-
'$relatedTo': {
151-
key: 'roles',
152-
object: rolePointer
153-
}
153+
'roles': rolePointer
154154
};
155155
var query = new RestQuery(this.config, master(this.config), '_Role',
156156
restWhere, {});
@@ -161,6 +161,10 @@ Auth.prototype._getAllRoleNamesForId = function(roleID) {
161161
}
162162
var roleIDs = results.map(r => r.objectId);
163163

164+
// we found a list of roles where the roleID
165+
// is referenced in the roles relation,
166+
// Get the roles where those found roles are also
167+
// referenced the same way
164168
var parentRolesPromises = roleIDs.map( (roleId) => {
165169
return this._getAllRoleNamesForId(roleId);
166170
});
@@ -169,14 +173,9 @@ Auth.prototype._getAllRoleNamesForId = function(roleID) {
169173
}).then(function(results){
170174
// Flatten
171175
let roleIDs = results.reduce( (memo, result) => {
172-
if (typeof result == "object") {
173-
memo = memo.concat(result);
174-
} else {
175-
memo.push(result);
176-
}
177-
return memo;
176+
return memo.concat(result);
178177
}, []);
179-
return Promise.resolve(roleIDs);
178+
return Promise.resolve([...new Set(roleIDs)]);
180179
});
181180
};
182181

0 commit comments

Comments
 (0)