diff --git a/CHANGELOG.md b/CHANGELOG.md index 031cbd36..36318bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,10 @@ #### Improvements: * Adds Pipeline Operator to Aggregate Router -#### Dependency updates +#### Bug Fixes: +* Fixes issue that prevented ACL's from being used with `select` (see [#571](https://github.com/parse-community/Parse-SDK-JS/issues/571)) + +#### Dependency updates: * [@parse/simple-mailgun-adapter@1.1.0](https://www.npmjs.com/package/@parse/simple-mailgun-adapter) ### 2.8.4 diff --git a/spec/ParseObject.spec.js b/spec/ParseObject.spec.js index ac16be0e..ecac81ba 100644 --- a/spec/ParseObject.spec.js +++ b/spec/ParseObject.spec.js @@ -1762,6 +1762,38 @@ describe('Parse.Object testing', () => { }) }); + it('should include ACLs with select', (done) => { + const score = new Parse.Object("GameScore"); + const player = new Parse.Object("Player"); + score.set({ + "score": 1234 + }); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + acl.setPublicWriteAccess(false); + + score.save().then(() => { + player.set("gameScore", score); + player.set("other", "value"); + player.setACL(acl); + return player.save(); + }).then(() => { + const query = new Parse.Query("Player"); + query.include("gameScore"); + query.select("gameScore"); + return query.find(); + }).then((res) => { + const obj = res[0]; + const gameScore = obj.get("gameScore"); + const other = obj.get("other"); + expect(other).toBeUndefined(); + expect(gameScore).not.toBeUndefined(); + expect(gameScore.get("score")).toBe(1234); + expect(obj.getACL().getPublicReadAccess()).toBe(true); + expect(obj.getACL().getPublicWriteAccess()).toBe(false); + }).then(done).catch(done.fail); + }); + it ('Update object field should store exactly same sent object', async (done) => { let object = new TestObject(); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index a150be1a..0e62d2e9 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -470,7 +470,12 @@ export class MongoStorageAdapter implements StorageAdapter { const mongoWhere = transformWhere(className, query, schema); const mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema)); const mongoKeys = _.reduce(keys, (memo, key) => { - memo[transformKey(className, key, schema)] = 1; + if (key === 'ACL') { + memo['_rperm'] = 1; + memo['_wperm'] = 1; + } else { + memo[transformKey(className, key, schema)] = 1; + } return memo; }, {}); diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 2df5abb6..c7a686f8 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -1437,9 +1437,16 @@ export class PostgresStorageAdapter implements StorageAdapter { let columns = '*'; if (keys) { // Exclude empty keys - keys = keys.filter((key) => { - return key.length > 0; - }); + // Replace ACL by it's keys + keys = keys.reduce((memo, key) => { + if (key === 'ACL') { + memo.push('_rperm'); + memo.push('_wperm'); + } else if (key.length > 0) { + memo.push(key); + } + return memo; + }, []); columns = keys.map((key, index) => { if (key === '$score') { return `ts_rank_cd(to_tsvector($${2}, $${3}:name), to_tsquery($${4}, $${5}), 32) as score`; diff --git a/src/RestQuery.js b/src/RestQuery.js index 8b286e30..20dcb1ea 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -5,7 +5,7 @@ var SchemaController = require('./Controllers/SchemaController'); var Parse = require('parse/node').Parse; const triggers = require('./triggers'); -const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt']; +const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt', 'ACL']; // restOptions can include: // skip // limit