Makes sure pointer includes are interpolated as get (#2747)

* test for repro #2005

* Adds ability to override CLP op from RestQuery.execute

* nits
This commit is contained in:
Florent Vilmart
2016-09-24 14:54:31 -04:00
committed by GitHub
parent 9260e8b05f
commit b5af4d017c
3 changed files with 44 additions and 12 deletions

View File

@@ -1548,6 +1548,34 @@ describe('schemas', () => {
}); });
}); });
it('can query with include and CLP (issue #2005)', (done) => {
setPermissionsOnClass('AnotherObject', {
get: {"*": true},
find: {},
create: {'*': true},
update: {'*': true},
delete: {'*': true},
addField:{'*': true}
}).then(() => {
let obj = new Parse.Object('AnObject');
let anotherObject = new Parse.Object('AnotherObject');
return obj.save({
anotherObject
})
}).then(() => {
let query = new Parse.Query('AnObject');
query.include('anotherObject');
return query.find();
}).then((res) => {
expect(res.length).toBe(1);
expect(res[0].get('anotherObject')).not.toBeUndefined();
done();
}).catch((err) => {
jfail(err);
done();
})
});
it('can add field as master (issue #1257)', (done) => { it('can add field as master (issue #1257)', (done) => {
setPermissionsOnClass('AClass', { setPermissionsOnClass('AClass', {
'addField': {} 'addField': {}

View File

@@ -721,11 +721,12 @@ DatabaseController.prototype.find = function(className, query, {
acl, acl,
sort = {}, sort = {},
count, count,
keys keys,
op
} = {}) { } = {}) {
let isMaster = acl === undefined; let isMaster = acl === undefined;
let aclGroup = acl || []; let aclGroup = acl || [];
let op = typeof query.objectId == 'string' && Object.keys(query).length === 1 ? 'get' : 'find'; op = op || (typeof query.objectId == 'string' && Object.keys(query).length === 1 ? 'get' : 'find');
let classExists = true; let classExists = true;
return this.loadSchema() return this.loadSchema()
.then(schemaController => { .then(schemaController => {

View File

@@ -113,11 +113,11 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl
// Returns a promise for the response - an object with optional keys // Returns a promise for the response - an object with optional keys
// 'results' and 'count'. // 'results' and 'count'.
// TODO: consolidate the replaceX functions // TODO: consolidate the replaceX functions
RestQuery.prototype.execute = function() { RestQuery.prototype.execute = function(executeOptions) {
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
return this.buildRestWhere(); return this.buildRestWhere();
}).then(() => { }).then(() => {
return this.runFind(); return this.runFind(executeOptions);
}).then(() => { }).then(() => {
return this.runCount(); return this.runCount();
}).then(() => { }).then(() => {
@@ -387,18 +387,22 @@ RestQuery.prototype.replaceDontSelect = function() {
// Returns a promise for whether it was successful. // Returns a promise for whether it was successful.
// Populates this.response with an object that only has 'results'. // Populates this.response with an object that only has 'results'.
RestQuery.prototype.runFind = function() { RestQuery.prototype.runFind = function(options = {}) {
if (this.findOptions.limit === 0) { if (this.findOptions.limit === 0) {
this.response = {results: []}; this.response = {results: []};
return Promise.resolve(); return Promise.resolve();
} }
let findOptions = Object.assign({}, this.findOptions);
if (this.keys) { if (this.keys) {
this.findOptions.keys = Array.from(this.keys).map((key) => { findOptions.keys = Array.from(this.keys).map((key) => {
return key.split('.')[0]; return key.split('.')[0];
}); });
} }
if (options.op) {
findOptions.op = options.op;
}
return this.config.database.find( return this.config.database.find(
this.className, this.restWhere, this.findOptions).then((results) => { this.className, this.restWhere, findOptions).then((results) => {
if (this.className === '_User') { if (this.className === '_User') {
for (var result of results) { for (var result of results) {
delete result.password; delete result.password;
@@ -473,7 +477,6 @@ function includePath(config, auth, response, path, restOptions = {}) {
return response; return response;
} }
let pointersHash = {}; let pointersHash = {};
var objectIds = {};
for (var pointer of pointers) { for (var pointer of pointers) {
if (!pointer) { if (!pointer) {
continue; continue;
@@ -481,8 +484,8 @@ function includePath(config, auth, response, path, restOptions = {}) {
let className = pointer.className; let className = pointer.className;
// only include the good pointers // only include the good pointers
if (className) { if (className) {
pointersHash[className] = pointersHash[className] || []; pointersHash[className] = pointersHash[className] || new Set();
pointersHash[className].push(pointer.objectId); pointersHash[className].add(pointer.objectId);
} }
} }
@@ -504,9 +507,9 @@ function includePath(config, auth, response, path, restOptions = {}) {
} }
let queryPromises = Object.keys(pointersHash).map((className) => { let queryPromises = Object.keys(pointersHash).map((className) => {
var where = {'objectId': {'$in': pointersHash[className]}}; let where = {'objectId': {'$in': Array.from(pointersHash[className])}};
var query = new RestQuery(config, auth, className, where, includeRestOptions); var query = new RestQuery(config, auth, className, where, includeRestOptions);
return query.execute().then((results) => { return query.execute({op: 'get'}).then((results) => {
results.className = className; results.className = className;
return Promise.resolve(results); return Promise.resolve(results);
}) })