From 18dd5f9acb94f53cfd32d967074e27278408c710 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 3 Nov 2022 21:23:24 +1100 Subject: [PATCH 1/7] feat: change default for enforcePrivateUsers --- src/Options/Definitions.js | 2 +- src/Options/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index d8e3f841dd..21c5ea3695 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -210,7 +210,7 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_ENFORCE_PRIVATE_USERS', help: 'Set to true if new users should be created without public read and write access.', action: parsers.booleanParser, - default: false, + default: true, }, expireInactiveSessions: { env: 'PARSE_SERVER_EXPIRE_INACTIVE_SESSIONS', diff --git a/src/Options/index.js b/src/Options/index.js index 2592e1e441..f3e08a1760 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -280,7 +280,7 @@ export interface ParseServerOptions { :DEFAULT: {} */ security: ?SecurityOptions; /* Set to true if new users should be created without public read and write access. - :DEFAULT: false */ + :DEFAULT: true */ enforcePrivateUsers: ?boolean; /* An array of keys and values that are prohibited in database read and write requests to prevent potential security vulnerabilities. It is possible to specify only a key (`{"key":"..."}`), only a value (`{"value":"..."}`) or a key-value pair (`{"key":"...","value":"..."}`). The specification can use the following types: `boolean`, `numeric` or `string`, where `string` will be interpreted as a regex notation. Request data is deep-scanned for matching definitions to detect also any nested occurrences. Defaults are patterns that are likely to be used in malicious requests. Setting this option will override the default patterns. :DEFAULT: [{"key":"_bsontype","value":"Code"},{"key":"constructor"},{"key":"__proto__"}] */ From 49da39095f7cca6e4512461c96e1df66ffa92a65 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 3 Nov 2022 21:27:52 +1100 Subject: [PATCH 2/7] Update Deprecations.js --- src/Deprecator/Deprecations.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Deprecator/Deprecations.js b/src/Deprecator/Deprecations.js index 1c3d336be9..2361db3f53 100644 --- a/src/Deprecator/Deprecations.js +++ b/src/Deprecator/Deprecations.js @@ -22,6 +22,5 @@ module.exports = [ solution: "Additionally, the environment variable 'PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS' will be deprecated and renamed to 'PARSE_SERVER_DIRECT_ACCESS' in a future version; it is currently possible to use either one.", }, - { optionKey: 'enforcePrivateUsers', changeNewDefault: 'true' }, { optionKey: 'allowClientClassCreation', changeNewDefault: 'false' }, ]; From 2a9381a958032c8fdd699c6ff892b086f252b4cb Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 3 Nov 2022 22:13:11 +1100 Subject: [PATCH 3/7] fix tests --- spec/ParseGraphQLServer.spec.js | 20 ++++++++++-- spec/ParseLiveQuery.spec.js | 3 ++ spec/ParseSession.spec.js | 6 ++++ spec/ParseUser.spec.js | 40 +++++++++++++++++++----- spec/ProtectedFields.spec.js | 12 +++++++ spec/RestQuery.spec.js | 1 + spec/UserPII.spec.js | 4 ++- spec/ValidationAndPasswordsReset.spec.js | 2 +- 8 files changed, 76 insertions(+), 12 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 205de6263c..e5f994ff1b 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -292,30 +292,37 @@ describe('ParseGraphQLServer', () => { let objects = []; async function prepareData() { + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); user1 = new Parse.User(); user1.setUsername('user1'); user1.setPassword('user1'); user1.setEmail('user1@user1.user1'); + user1.setACL(acl); await user1.signUp(); user2 = new Parse.User(); user2.setUsername('user2'); user2.setPassword('user2'); + user2.setACL(acl); await user2.signUp(); user3 = new Parse.User(); user3.setUsername('user3'); user3.setPassword('user3'); + user3.setACL(acl); await user3.signUp(); user4 = new Parse.User(); user4.setUsername('user4'); user4.setPassword('user4'); + user4.setACL(acl); await user4.signUp(); user5 = new Parse.User(); user5.setUsername('user5'); user5.setPassword('user5'); + user5.setACL(acl); await user5.signUp(); const roleACL = new Parse.ACL(); @@ -7064,6 +7071,7 @@ describe('ParseGraphQLServer', () => { username: 'user2', password: 'user2', someField: 'someValue2', + ACL: { public: { read: true, write: true } }, }, }, someField: 'someValue', @@ -7130,6 +7138,7 @@ describe('ParseGraphQLServer', () => { username: 'user2', password: 'user2', someField: 'someValue2', + ACL: { public: { read: true, write: true } }, }, }, }, @@ -8155,19 +8164,21 @@ describe('ParseGraphQLServer', () => { const someClass = new Parse.Object('SomeClass'); await someClass.save(); + const roleACL = new Parse.ACL(); + roleACL.setPublicReadAccess(true); + const user = new Parse.User(); user.set('username', 'username'); user.set('password', 'password'); + user.setACL(roleACL); await user.signUp(); const user2 = new Parse.User(); user2.set('username', 'username2'); user2.set('password', 'password2'); + user2.setACL(roleACL); await user2.signUp(); - const roleACL = new Parse.ACL(); - roleACL.setPublicReadAccess(true); - const role = new Parse.Role('aRole', roleACL); await role.save(); @@ -10444,6 +10455,9 @@ describe('ParseGraphQLServer', () => { const user = new Parse.User(); user.setUsername('user1'); user.setPassword('user1'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); await user.signUp(); await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js index d112fceded..cc96862350 100644 --- a/spec/ParseLiveQuery.spec.js +++ b/spec/ParseLiveQuery.spec.js @@ -1076,6 +1076,9 @@ describe('ParseLiveQuery', function () { user.setUsername('username'); user.setPassword('password'); user.set('foo', 'bar'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); const query = new Parse.Query(Parse.User); query.equalTo('foo', 'bar'); diff --git a/spec/ParseSession.spec.js b/spec/ParseSession.spec.js index a85be1a95e..aca4c07263 100644 --- a/spec/ParseSession.spec.js +++ b/spec/ParseSession.spec.js @@ -6,6 +6,8 @@ const request = require('../lib/request'); function setupTestUsers() { + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); const user1 = new Parse.User(); const user2 = new Parse.User(); const user3 = new Parse.User(); @@ -18,6 +20,10 @@ function setupTestUsers() { user2.set('password', 'password'); user3.set('password', 'password'); + user1.setACL(acl); + user2.setACL(acl); + user3.setACL(acl); + return user1 .signUp() .then(() => { diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 92301316e4..ee6f847428 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -139,14 +139,13 @@ describe('Parse.User testing', () => { const ACL = user.getACL(); expect(ACL.getReadAccess(user)).toBe(true); expect(ACL.getWriteAccess(user)).toBe(true); - expect(ACL.getPublicReadAccess()).toBe(true); + expect(ACL.getPublicReadAccess()).toBe(false); expect(ACL.getPublicWriteAccess()).toBe(false); const perms = ACL.permissionsById; - expect(Object.keys(perms).length).toBe(2); + expect(Object.keys(perms).length).toBe(1); expect(perms[user.id].read).toBe(true); expect(perms[user.id].write).toBe(true); - expect(perms['*'].read).toBe(true); - expect(perms['*'].write).not.toBe(true); + expect(perms['*']).toBeUndefined(); done(); }); @@ -818,7 +817,7 @@ describe('Parse.User testing', () => { kevin.set('password', 'mypass'); await kevin.signUp(); const query = new Parse.Query(Parse.User); - const count = await query.count(); + const count = await query.count({ useMasterKey: true }); equal(count, 2); done(); }); @@ -2076,7 +2075,15 @@ describe('Parse.User testing', () => { }); it("querying for users doesn't get session tokens", done => { - Parse.User.signUp('finn', 'human', { foo: 'bar' }) + const user = new Parse.User(); + user.set('username', 'finn'); + user.set('password', 'human'); + user.set('foo', 'bar'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); + user + .signUp() .then(function () { return Parse.User.logOut(); }) @@ -2085,6 +2092,9 @@ describe('Parse.User testing', () => { user.set('username', 'jake'); user.set('password', 'dog'); user.set('foo', 'baz'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); return user.signUp(); }) .then(function () { @@ -2111,7 +2121,14 @@ describe('Parse.User testing', () => { }); it('querying for users only gets the expected fields', done => { - Parse.User.signUp('finn', 'human', { foo: 'bar' }).then(() => { + const user = new Parse.User(); + user.setUsername('finn'); + user.setPassword('human'); + user.set('foo', 'bar'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); + user.signUp().then(() => { request({ headers: { 'X-Parse-Application-Id': 'test', @@ -3372,6 +3389,9 @@ describe('Parse.User testing', () => { password: 'world', email: 'test@email.com', }); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); reconfigureServer({ appName: 'unused', @@ -4003,6 +4023,12 @@ describe('Parse.User testing', () => { silent: true, }); + Parse.Cloud.beforeSave(Parse.User, ({ object }) => { + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + object.setACL(acl); + }); + const query = new Parse.Query(Parse.User); query.doesNotExist('foo'); const subscription = await query.subscribe(); diff --git a/spec/ProtectedFields.spec.js b/spec/ProtectedFields.spec.js index 53673e8e02..8195985dcb 100644 --- a/spec/ProtectedFields.spec.js +++ b/spec/ProtectedFields.spec.js @@ -13,6 +13,9 @@ describe('ProtectedFields', function () { user.setPassword('sekrit'); user.set('email', 'alice@aol.com'); user.set('favoriteColor', 'yellow'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); await user.save(); const fetched = await new Parse.Query(Parse.User).get(user.id); @@ -35,6 +38,9 @@ describe('ProtectedFields', function () { user.set('timeZone', 'America/Los_Angeles'); user.set('favoriteColor', 'yellow'); user.set('favoriteFood', 'pizza'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); await user.save(); const fetched = await new Parse.Query(Parse.User).get(user.id); @@ -57,6 +63,9 @@ describe('ProtectedFields', function () { user.set('timeZone', 'America/Los_Angeles'); user.set('favoriteColor', 'yellow'); user.set('favoriteFood', 'pizza'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); await user.save(); const fetched = await new Parse.Query(Parse.User).get(user.id); @@ -108,6 +117,9 @@ describe('ProtectedFields', function () { user.set('timeZone', 'America/Los_Angeles'); user.set('favoriteColor', 'yellow'); user.set('favoriteFood', 'pizza'); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + user.setACL(acl); await user.save(); const objA = await new Parse.Object('ClassA').set('foo', 'zzz').set('bar', 'yyy').save(); diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js index 02af2fc576..24e22ac4f5 100644 --- a/spec/RestQuery.spec.js +++ b/spec/RestQuery.spec.js @@ -96,6 +96,7 @@ describe('rest query', () => { let user = { username: 'aUsername', password: 'aPassword', + ACL: { '*': { read: true } }, }; const activity = { type: 'comment', diff --git a/spec/UserPII.spec.js b/spec/UserPII.spec.js index 87bfe15e4e..5416068f0e 100644 --- a/spec/UserPII.spec.js +++ b/spec/UserPII.spec.js @@ -16,7 +16,9 @@ describe('Personally Identifiable Information', () => { await reconfigureServer(); user = await Parse.User.signUp('tester', 'abc'); user = await Parse.User.logIn(user.get('username'), 'abc'); - await user.set('email', EMAIL).set('zip', ZIP).set('ssn', SSN).save(); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + await user.set('email', EMAIL).set('zip', ZIP).set('ssn', SSN).setACL(acl).save(); done(); }); diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js index d7cc72c7b0..a8ae169cf0 100644 --- a/spec/ValidationAndPasswordsReset.spec.js +++ b/spec/ValidationAndPasswordsReset.spec.js @@ -276,7 +276,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => { 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user' ); user - .fetch() + .fetch({ useMasterKey: true }) .then( () => { expect(user.get('emailVerified')).toEqual(true); From 3372ec60b58031bfa93374ed7e757b6705556bdb Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 3 Nov 2022 22:44:16 +1100 Subject: [PATCH 4/7] Update ParseUser.spec.js --- spec/ParseUser.spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index ee6f847428..96f1b41d11 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -808,13 +808,17 @@ describe('Parse.User testing', () => { }); it('count users', async done => { + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); const james = new Parse.User(); james.set('username', 'james'); james.set('password', 'mypass'); + james.setACL(acl); await james.signUp(); const kevin = new Parse.User(); kevin.set('username', 'kevin'); kevin.set('password', 'mypass'); + kevin.setACL(acl); await kevin.signUp(); const query = new Parse.Query(Parse.User); const count = await query.count({ useMasterKey: true }); From cda251bf953f2b5ad181762a7eda971138d743bc Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 4 Nov 2022 10:45:48 +1100 Subject: [PATCH 5/7] Update ParseUser.spec.js --- spec/ParseUser.spec.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 96f1b41d11..d133ebc66d 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -808,21 +808,17 @@ describe('Parse.User testing', () => { }); it('count users', async done => { - const acl = new Parse.ACL(); - acl.setPublicReadAccess(true); const james = new Parse.User(); james.set('username', 'james'); james.set('password', 'mypass'); - james.setACL(acl); await james.signUp(); const kevin = new Parse.User(); kevin.set('username', 'kevin'); kevin.set('password', 'mypass'); - kevin.setACL(acl); await kevin.signUp(); const query = new Parse.Query(Parse.User); - const count = await query.count({ useMasterKey: true }); - equal(count, 2); + const count = await query.find({ useMasterKey: true }); + equal(count.length, 2); done(); }); From 33d58de9fc266404a007eb44ebcd9b75ebb94a49 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 14 Nov 2022 23:59:47 +0100 Subject: [PATCH 6/7] test: use master key client to create user --- spec/ParseGraphQLServer.spec.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 559252252a..bb6d2702aa 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -7040,7 +7040,7 @@ describe('ParseGraphQLServer', () => { options: { anOption: true }, }; - it('should create user and return authData response', async () => { + fit('should create user and return authData response', async () => { parseServer = await global.reconfigureServer({ publicServerURL: 'http://localhost:13377/parse', auth: { @@ -7073,6 +7073,11 @@ describe('ParseGraphQLServer', () => { }, }, }, + context: { + headers: { + 'X-Parse-Master-Key': 'test', + }, + }, }); expect(result.data.createUser.clientMutationId).toEqual(clientMutationId); From b1d6d05decc492279cf4519f49ca8ee776da00dd Mon Sep 17 00:00:00 2001 From: dblythy Date: Tue, 15 Nov 2022 12:33:50 +1100 Subject: [PATCH 7/7] fix tests --- DEPRECATIONS.md | 2 +- spec/ParseGraphQLServer.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md index 01caca394c..053dd9fb2b 100644 --- a/DEPRECATIONS.md +++ b/DEPRECATIONS.md @@ -6,7 +6,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h |--------|-------------------------------------------------|----------------------------------------------------------------------|---------------------------------|---------------------------------|-----------------------|-------| | DEPPS1 | Native MongoDB syntax in aggregation pipeline | [#7338](https://github.com/parse-community/parse-server/issues/7338) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | | DEPPS2 | Config option `directAccess` defaults to `true` | [#6636](https://github.com/parse-community/parse-server/pull/6636) | 5.0.0 (2022) | 6.0.0 (2023) | removed | - | -| DEPPS3 | Config option `enforcePrivateUsers` defaults to `true` | [#7319](https://github.com/parse-community/parse-server/pull/7319) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | +| DEPPS3 | Config option `enforcePrivateUsers` defaults to `true` | [#7319](https://github.com/parse-community/parse-server/pull/7319) | 5.0.0 (2022) | 6.0.0 (2023) | removed | - | | DEPPS4 | Remove convenience method for http request `Parse.Cloud.httpRequest` | [#7589](https://github.com/parse-community/parse-server/pull/7589) | 5.0.0 (2022) | 6.0.0 (2023) | removed | - | | DEPPS5 | Config option `allowClientClassCreation` defaults to `false` | [#7925](https://github.com/parse-community/parse-server/pull/7925) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | | DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index bb6d2702aa..6bdd3b10f5 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -7040,7 +7040,7 @@ describe('ParseGraphQLServer', () => { options: { anOption: true }, }; - fit('should create user and return authData response', async () => { + it('should create user and return authData response', async () => { parseServer = await global.reconfigureServer({ publicServerURL: 'http://localhost:13377/parse', auth: {