From eb620f2d1a12414ecd21ecae67974f2eaa5804e6 Mon Sep 17 00:00:00 2001 From: waseemAlhalabi Date: Sun, 4 Jan 2026 12:56:20 +0300 Subject: [PATCH 1/4] fix: Apply default ACL only on object creation, not update --- src/RestWrite.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index a0de5577a5..8ad1ab753c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -370,8 +370,8 @@ RestWrite.prototype.setRequiredFieldsIfNeeded = function () { } }; - // add default ACL - if ( + // add default ACL (only on CREATE, not UPDATE) + if (!this.query && schema?.classLevelPermissions?.ACL && !this.data.ACL && JSON.stringify(schema.classLevelPermissions.ACL) !== From 5c830dc7319e9515be75c339c2f1dcda4fe10279 Mon Sep 17 00:00:00 2001 From: waseemAlhalabi Date: Sun, 4 Jan 2026 13:57:24 +0300 Subject: [PATCH 2/4] test: Add tests for default ACL behavior on update --- spec/ParseACL.spec.js | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/spec/ParseACL.spec.js b/spec/ParseACL.spec.js index d8abc65c06..7621a3c1bc 100644 --- a/spec/ParseACL.spec.js +++ b/spec/ParseACL.spec.js @@ -951,4 +951,65 @@ describe('Parse.ACL', () => { expect(acl[user.id].write).toBeTrue(); expect(acl[user.id].read).toBeTrue(); }); + + it('should not overwrite ACL with defaultACL on update', async () => { + await new Parse.Object('TestObject').save(); + const schema = await Parse.Server.database.loadSchema(); + await schema.updateClass( + 'TestObject', + {}, + { + create: { '*': true }, + update: { '*': true }, + ACL: { + '*': { read: true }, + currentUser: { read: true, write: true }, + }, + } + ); + const user = await Parse.User.signUp('testuser', 'p@ssword'); + const obj = new Parse.Object('TestObject'); + await obj.save(null, { sessionToken: user.getSessionToken() }); + + const originalAcl = obj.getACL().toJSON(); + expect(originalAcl['*']).toEqual({ read: true }); + expect(originalAcl[user.id]).toEqual({ read: true, write: true }); + + obj.set('field', 'value'); + await obj.save(null, { sessionToken: user.getSessionToken() }); + + const updatedAcl = obj.getACL().toJSON(); + expect(updatedAcl).toEqual(originalAcl); + }); + + it('should allow explicit ACL modification on update', async () => { + await new Parse.Object('TestObject').save(); + const schema = await Parse.Server.database.loadSchema(); + await schema.updateClass( + 'TestObject', + {}, + { + create: { '*': true }, + update: { '*': true }, + ACL: { + '*': { read: true }, + currentUser: { read: true, write: true }, + }, + } + ); + const user = await Parse.User.signUp('testuser', 'p@ssword'); + const obj = new Parse.Object('TestObject'); + await obj.save(null, { sessionToken: user.getSessionToken() }); + + const customAcl = new Parse.ACL(); + customAcl.setPublicReadAccess(false); + customAcl.setReadAccess(user.id, true); + customAcl.setWriteAccess(user.id, true); + obj.setACL(customAcl); + await obj.save(null, { sessionToken: user.getSessionToken() }); + + const updatedAcl = obj.getACL().toJSON(); + expect(updatedAcl['*']).toBeUndefined(); + expect(updatedAcl[user.id]).toEqual({ read: true, write: true }); + }); }); From e40ac3bfae6d65b3eb366eba3ff9798c4c05e5bd Mon Sep 17 00:00:00 2001 From: waseemAlhalabi Date: Tue, 27 Jan 2026 10:57:32 +0300 Subject: [PATCH 3/4] style: Remove trailing whitespace in RestWrite.js --- src/RestWrite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 8ad1ab753c..9bb25e4ac3 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -371,7 +371,7 @@ RestWrite.prototype.setRequiredFieldsIfNeeded = function () { }; // add default ACL (only on CREATE, not UPDATE) - if (!this.query && + if (!this.query && schema?.classLevelPermissions?.ACL && !this.data.ACL && JSON.stringify(schema.classLevelPermissions.ACL) !== From 73fdafb39359eb63e054087bf4f84640a388a42f Mon Sep 17 00:00:00 2001 From: "@yazan.alkhalil" Date: Fri, 13 Feb 2026 21:48:32 +0300 Subject: [PATCH 4/4] fix: Add missing addField CLP in default ACL update test The test "should not overwrite ACL with defaultACL on update" was failing with "Permission denied" (code 119) because the CLP configuration was missing the addField permission. When the test called obj.set('field', 'value'), it attempted to add a new field to the class, which requires addField CLP permission. Without it, addField defaults to {} (no access), causing the operation to be rejected. --- spec/ParseACL.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/ParseACL.spec.js b/spec/ParseACL.spec.js index 7621a3c1bc..f2d2cbd8b3 100644 --- a/spec/ParseACL.spec.js +++ b/spec/ParseACL.spec.js @@ -961,6 +961,7 @@ describe('Parse.ACL', () => { { create: { '*': true }, update: { '*': true }, + addField: { '*': true }, ACL: { '*': { read: true }, currentUser: { read: true, write: true },