Skip to content

Commit 5f7d0e0

Browse files
authored
Merge 74a7555 into 95da5d6
2 parents 95da5d6 + 74a7555 commit 5f7d0e0

File tree

3 files changed

+130
-30
lines changed

3 files changed

+130
-30
lines changed

spec/ParseRole.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ describe('Parse Role testing', () => {
188188

189189
// 1 call for the 1st layer of roles
190190
// 1 call for the 2nd layer
191-
expect(getAllRolesSpy.calls.count()).toEqual(2);
191+
expect(getAllRolesSpy.calls.count()).toEqual(
192+
process.env.PARSE_SERVER_TEST_DB === 'postgres' ? 2 : 1
193+
);
192194
done();
193195
})
194196
.catch(() => {

src/Auth.js

Lines changed: 126 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Deprecator from './Deprecator/Deprecator';
55
import { logger } from './logger';
66
import RestQuery from './RestQuery';
77
import RestWrite from './RestWrite';
8+
import MongoStorageAdapter from './Adapters/Storage/Mongo/MongoStorageAdapter';
89

910
// An Auth object tells you who is requesting something and whether
1011
// the master key was used.
@@ -139,7 +140,6 @@ const getAuthForSessionToken = async function ({
139140
limit: 1,
140141
include: 'user',
141142
};
142-
const RestQuery = require('./RestQuery');
143143
const query = new RestQuery(config, master(config), '_Session', { sessionToken }, restOptions);
144144
results = (await query.execute()).results;
145145
} else {
@@ -183,7 +183,6 @@ var getAuthForLegacySessionToken = function ({ config, sessionToken, installatio
183183
var restOptions = {
184184
limit: 1,
185185
};
186-
const RestQuery = require('./RestQuery');
187186
var query = new RestQuery(config, master(config), '_User', { sessionToken }, restOptions);
188187
return query.execute().then(response => {
189188
var results = response.results;
@@ -221,17 +220,113 @@ Auth.prototype.getRolesForUser = async function () {
221220
//Stack all Parse.Role
222221
const results = [];
223222
if (this.config) {
224-
const restWhere = {
225-
users: {
226-
__type: 'Pointer',
227-
className: '_User',
228-
objectId: this.user.id,
229-
},
230-
};
231-
const RestQuery = require('./RestQuery');
232-
await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result =>
233-
results.push(result)
234-
);
223+
if (this.config.database.adapter instanceof MongoStorageAdapter) {
224+
const prefix = this.config.databaseAdapter._collectionPrefix || '';
225+
const result = await new RestQuery(
226+
this.config,
227+
master(this.config),
228+
'_Join:users:_Role',
229+
{},
230+
{
231+
pipeline: [
232+
{
233+
$match: {
234+
relatedId: this.user.id,
235+
},
236+
},
237+
{
238+
$graphLookup: {
239+
from: `${prefix}_Join:roles:_Role`,
240+
startWith: '$owningId',
241+
connectFromField: 'owningId',
242+
connectToField: 'relatedId',
243+
as: 'childRolePath',
244+
},
245+
},
246+
{
247+
$facet: {
248+
directRoles: [
249+
{
250+
$lookup: {
251+
from: `${prefix}_Role`,
252+
localField: 'owningId',
253+
foreignField: '_id',
254+
as: 'Roles',
255+
},
256+
},
257+
{
258+
$unwind: {
259+
path: '$Roles',
260+
},
261+
},
262+
{
263+
$replaceRoot: {
264+
newRoot: {
265+
$ifNull: ['$Roles', { $literal: {} }],
266+
},
267+
},
268+
},
269+
{
270+
$project: {
271+
name: 1,
272+
},
273+
},
274+
],
275+
childRoles: [
276+
{
277+
$lookup: {
278+
from: `${prefix}_Role`,
279+
localField: 'childRolePath.owningId',
280+
foreignField: '_id',
281+
as: 'Roles',
282+
},
283+
},
284+
{
285+
$unwind: {
286+
path: '$Roles',
287+
},
288+
},
289+
{
290+
$replaceRoot: {
291+
newRoot: {
292+
$ifNull: ['$Roles', { $literal: {} }],
293+
},
294+
},
295+
},
296+
{
297+
$project: {
298+
name: 1,
299+
},
300+
},
301+
],
302+
},
303+
},
304+
],
305+
}
306+
).execute();
307+
const { directRoles, childRoles } = result.results[0] || {
308+
directRoles: [],
309+
childRoles: [],
310+
};
311+
const roles = [...directRoles, ...childRoles];
312+
for (const role of roles) {
313+
const roleName = `role:${role.name}`;
314+
if (!results.includes(roleName)) {
315+
results.push(role);
316+
}
317+
}
318+
} else {
319+
const restWhere = {
320+
users: {
321+
__type: 'Pointer',
322+
className: '_User',
323+
objectId: this.user.id,
324+
},
325+
};
326+
await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result =>
327+
results.push(result)
328+
);
329+
}
235330
} else {
236331
await new Parse.Query(Parse.Role)
237332
.equalTo('users', this.user)
@@ -257,25 +352,29 @@ Auth.prototype._loadRoles = async function () {
257352
this.userRoles = [];
258353
this.fetchedRoles = true;
259354
this.rolePromise = null;
260-
261355
this.cacheRoles();
262356
return this.userRoles;
263357
}
264358

265-
const rolesMap = results.reduce(
266-
(m, r) => {
267-
m.names.push(r.name);
268-
m.ids.push(r.objectId);
269-
return m;
270-
},
271-
{ ids: [], names: [] }
272-
);
359+
if (typeof results[0] === 'object') {
360+
const rolesMap = results.reduce(
361+
(m, r) => {
362+
m.names.push(r.name);
363+
m.ids.push(r.objectId);
364+
return m;
365+
},
366+
{ ids: [], names: [] }
367+
);
368+
369+
// run the recursive finding
370+
const roleNames = await this._getAllRolesNamesForRoleIds(rolesMap.ids, rolesMap.names);
371+
this.userRoles = roleNames.map(r => {
372+
return 'role:' + r;
373+
});
374+
} else {
375+
this.userRoles = results;
376+
}
273377

274-
// run the recursive finding
275-
const roleNames = await this._getAllRolesNamesForRoleIds(rolesMap.ids, rolesMap.names);
276-
this.userRoles = roleNames.map(r => {
277-
return 'role:' + r;
278-
});
279378
this.fetchedRoles = true;
280379
this.rolePromise = null;
281380
this.cacheRoles();
@@ -322,7 +421,6 @@ Auth.prototype.getRolesByIds = async function (ins) {
322421
};
323422
});
324423
const restWhere = { roles: { $in: roles } };
325-
const RestQuery = require('./RestQuery');
326424
await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result =>
327425
results.push(result)
328426
);

src/Controllers/DatabaseController.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ class DatabaseController {
12931293
return this.adapter.distinct(className, schema, query, distinct);
12941294
}
12951295
} else if (pipeline) {
1296-
if (!classExists) {
1296+
if (!classExists && className.slice(0, 5) !== '_Join') {
12971297
return [];
12981298
} else {
12991299
return this.adapter.aggregate(

0 commit comments

Comments
 (0)