From 7b86cfb6c1cc52628bbe2f95004eb64afafe6396 Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 16 Apr 2020 17:09:37 -0400 Subject: [PATCH 1/3] Fixing objectId for Pointer in Postgres --- src/Adapters/Storage/Postgres/PostgresStorageAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 7830a83c65..6b58120778 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -37,7 +37,7 @@ const parseTypeToPostgresType = (type) => { case 'Boolean': return 'boolean'; case 'Pointer': - return 'char(10)'; + return 'text'; case 'Number': return 'double precision'; case 'GeoPoint': From b6babfe0f401d8b7c9a76d6d4bb3c89c89b1f7f7 Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 16 Apr 2020 19:14:00 -0400 Subject: [PATCH 2/3] add test case for longer objectId pointer. Note that this test fails on Postgres before the addition of previous commit --- spec/rest.spec.js | 211 +++++++++++++++++++++++++++------------------- 1 file changed, 125 insertions(+), 86 deletions(-) diff --git a/spec/rest.spec.js b/spec/rest.spec.js index 96bb223a16..538f1b4cb2 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -16,11 +16,11 @@ describe('rest create', () => { database = config.database; }); - it('handles _id', done => { + it('handles _id', (done) => { rest .create(config, auth.nobody(config), 'Foo', {}) .then(() => database.adapter.find('Foo', { fields: {} }, {}, {})) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const obj = results[0]; expect(typeof obj.objectId).toEqual('string'); @@ -30,12 +30,12 @@ describe('rest create', () => { }); }); - it('can use custom _id size', done => { + it('can use custom _id size', (done) => { config.objectIdSize = 20; rest .create(config, auth.nobody(config), 'Foo', {}) .then(() => database.adapter.find('Foo', { fields: {} }, {}, {})) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const obj = results[0]; expect(typeof obj.objectId).toEqual('string'); @@ -104,14 +104,14 @@ describe('rest create', () => { expect(objectId).toBeDefined(); }); - it('is backwards compatible when _id size changes', done => { + it('is backwards compatible when _id size changes', (done) => { rest .create(config, auth.nobody(config), 'Foo', { size: 10 }) .then(() => { config.objectIdSize = 20; return rest.find(config, auth.nobody(config), 'Foo', { size: 10 }); }) - .then(response => { + .then((response) => { expect(response.results.length).toEqual(1); expect(response.results[0].objectId.length).toEqual(10); return rest.update( @@ -125,7 +125,7 @@ describe('rest create', () => { .then(() => { return rest.find(config, auth.nobody(config), 'Foo', { size: 10 }); }) - .then(response => { + .then((response) => { expect(response.results.length).toEqual(1); expect(response.results[0].objectId.length).toEqual(10); expect(response.results[0].update).toEqual(20); @@ -135,14 +135,14 @@ describe('rest create', () => { config.objectIdSize = 10; return rest.find(config, auth.nobody(config), 'Foo', { size: 20 }); }) - .then(response => { + .then((response) => { expect(response.results.length).toEqual(1); expect(response.results[0].objectId.length).toEqual(20); done(); }); }); - it('handles array, object, date', done => { + it('handles array, object, date', (done) => { const now = new Date(); const obj = { array: [1, 2, 3], @@ -165,7 +165,7 @@ describe('rest create', () => { {} ) ) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const mob = results[0]; expect(mob.array instanceof Array).toBe(true); @@ -176,17 +176,17 @@ describe('rest create', () => { }); }); - it('handles object and subdocument', done => { + it('handles object and subdocument', (done) => { const obj = { subdoc: { foo: 'bar', wu: 'tan' } }; - Parse.Cloud.beforeSave('MyClass', function() { + Parse.Cloud.beforeSave('MyClass', function () { // this beforeSave trigger should do nothing but can mess with the object }); rest .create(config, auth.nobody(config), 'MyClass', obj) .then(() => database.adapter.find('MyClass', { fields: {} }, {}, {})) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const mob = results[0]; expect(typeof mob.subdoc).toBe('object'); @@ -203,7 +203,7 @@ describe('rest create', () => { ); }) .then(() => database.adapter.find('MyClass', { fields: {} }, {}, {})) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const mob = results[0]; expect(typeof mob.subdoc).toBe('object'); @@ -214,7 +214,7 @@ describe('rest create', () => { .catch(done.fail); }); - it('handles create on non-existent class when disabled client class creation', done => { + it('handles create on non-existent class when disabled client class creation', (done) => { const customConfig = Object.assign({}, config, { allowClientClassCreation: false, }); @@ -230,7 +230,7 @@ describe('rest create', () => { fail('Should throw an error'); done(); }, - err => { + (err) => { expect(err.code).toEqual(Parse.Error.OPERATION_FORBIDDEN); expect(err.message).toEqual( 'This user is not allowed to access ' + @@ -262,13 +262,13 @@ describe('rest create', () => { ); }); - it('handles user signup', done => { + it('handles user signup', (done) => { const user = { username: 'asdf', password: 'zxcv', foo: 'bar', }; - rest.create(config, auth.nobody(config), '_User', user).then(r => { + rest.create(config, auth.nobody(config), '_User', user).then((r) => { expect(Object.keys(r.response).length).toEqual(3); expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); @@ -277,7 +277,7 @@ describe('rest create', () => { }); }); - it('handles anonymous user signup', done => { + it('handles anonymous user signup', (done) => { const data1 = { authData: { anonymous: { @@ -295,14 +295,14 @@ describe('rest create', () => { let username1; rest .create(config, auth.nobody(config), '_User', data1) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.sessionToken).toEqual('string'); expect(typeof r.response.username).toEqual('string'); return rest.create(config, auth.nobody(config), '_User', data1); }) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.username).toEqual('string'); @@ -310,13 +310,13 @@ describe('rest create', () => { username1 = r.response.username; return rest.create(config, auth.nobody(config), '_User', data2); }) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.sessionToken).toEqual('string'); return rest.create(config, auth.nobody(config), '_User', data2); }) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.username).toEqual('string'); @@ -326,7 +326,7 @@ describe('rest create', () => { }); }); - it('handles anonymous user signup and upgrade to new user', done => { + it('handles anonymous user signup and upgrade to new user', (done) => { const data1 = { authData: { anonymous: { @@ -343,7 +343,7 @@ describe('rest create', () => { let objectId; rest .create(config, auth.nobody(config), '_User', data1) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.sessionToken).toEqual('string'); @@ -353,7 +353,7 @@ describe('rest create', () => { sessionToken: r.response.sessionToken, }); }) - .then(sessionAuth => { + .then((sessionAuth) => { return rest.update( config, sessionAuth, @@ -367,18 +367,18 @@ describe('rest create', () => { return Parse.User.logIn('hello', 'world'); }); }) - .then(r => { + .then((r) => { expect(r.id).toEqual(objectId); expect(r.get('username')).toEqual('hello'); done(); }) - .catch(err => { + .catch((err) => { jfail(err); done(); }); }); - it('handles no anonymous users config', done => { + it('handles no anonymous users config', (done) => { const NoAnnonConfig = Object.assign({}, config); NoAnnonConfig.authDataManager.setEnableAnonymousUsers(false); const data1 = { @@ -393,7 +393,7 @@ describe('rest create', () => { fail('Should throw an error'); done(); }, - err => { + (err) => { expect(err.code).toEqual(Parse.Error.UNSUPPORTED_SERVICE); expect(err.message).toEqual( 'This authentication method is unsupported.' @@ -404,7 +404,7 @@ describe('rest create', () => { ); }); - it('test facebook signup and login', done => { + it('test facebook signup and login', (done) => { const data = { authData: { facebook: { @@ -416,14 +416,14 @@ describe('rest create', () => { let newUserSignedUpByFacebookObjectId; rest .create(config, auth.nobody(config), '_User', data) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.sessionToken).toEqual('string'); newUserSignedUpByFacebookObjectId = r.response.objectId; return rest.create(config, auth.nobody(config), '_User', data); }) - .then(r => { + .then((r) => { expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); expect(typeof r.response.username).toEqual('string'); @@ -433,19 +433,19 @@ describe('rest create', () => { sessionToken: r.response.sessionToken, }); }) - .then(response => { + .then((response) => { expect(response.results.length).toEqual(1); const output = response.results[0]; expect(output.user.objectId).toEqual(newUserSignedUpByFacebookObjectId); done(); }) - .catch(err => { + .catch((err) => { jfail(err); done(); }); }); - it('stores pointers', done => { + it('stores pointers', (done) => { const obj = { foo: 'bar', aPointer: { @@ -469,7 +469,7 @@ describe('rest create', () => { {} ) ) - .then(results => { + .then((results) => { expect(results.length).toEqual(1); const output = results[0]; expect(typeof output.foo).toEqual('string'); @@ -484,7 +484,46 @@ describe('rest create', () => { }); }); - it('cannot set objectId', done => { + it('stores pointers to objectIds larger than 10 characters', (done) => { + const obj = { + foo: 'bar', + aPointer: { + __type: 'Pointer', + className: 'JustThePointer', + objectId: '49F62F92-9B56-46E7-A3D4-BBD14C52F666', // make it 10 chars to match PG storage + }, + }; + rest + .create(config, auth.nobody(config), 'APointerDarkly', obj) + .then(() => + database.adapter.find( + 'APointerDarkly', + { + fields: { + foo: { type: 'String' }, + aPointer: { type: 'Pointer', targetClass: 'JustThePointer' }, + }, + }, + {}, + {} + ) + ) + .then((results) => { + expect(results.length).toEqual(1); + const output = results[0]; + expect(typeof output.foo).toEqual('string'); + expect(typeof output._p_aPointer).toEqual('undefined'); + expect(output._p_aPointer).toBeUndefined(); + expect(output.aPointer).toEqual({ + __type: 'Pointer', + className: 'JustThePointer', + objectId: '49F62F92-9B56-46E7-A3D4-BBD14C52F666', + }); + done(); + }); + }); + + it('cannot set objectId', (done) => { const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': 'test', @@ -498,7 +537,7 @@ describe('rest create', () => { foo: 'bar', objectId: 'hello', }), - }).then(fail, response => { + }).then(fail, (response) => { const b = response.data; expect(b.code).toEqual(105); expect(b.error).toEqual('objectId is an invalid field name.'); @@ -506,7 +545,7 @@ describe('rest create', () => { }); }); - it('cannot set id', done => { + it('cannot set id', (done) => { const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': 'test', @@ -520,7 +559,7 @@ describe('rest create', () => { foo: 'bar', id: 'hello', }), - }).then(fail, response => { + }).then(fail, (response) => { const b = response.data; expect(b.code).toEqual(105); expect(b.error).toEqual('id is an invalid field name.'); @@ -528,7 +567,7 @@ describe('rest create', () => { }); }); - it('test default session length', done => { + it('test default session length', (done) => { const user = { username: 'asdf', password: 'zxcv', @@ -538,7 +577,7 @@ describe('rest create', () => { rest .create(config, auth.nobody(config), '_User', user) - .then(r => { + .then((r) => { expect(Object.keys(r.response).length).toEqual(3); expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); @@ -547,7 +586,7 @@ describe('rest create', () => { sessionToken: r.response.sessionToken, }); }) - .then(r => { + .then((r) => { expect(r.results.length).toEqual(1); const session = r.results[0]; @@ -564,7 +603,7 @@ describe('rest create', () => { }); }); - it('test specified session length', done => { + it('test specified session length', (done) => { const user = { username: 'asdf', password: 'zxcv', @@ -576,7 +615,7 @@ describe('rest create', () => { rest .create(config, auth.nobody(config), '_User', user) - .then(r => { + .then((r) => { expect(Object.keys(r.response).length).toEqual(3); expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); @@ -585,7 +624,7 @@ describe('rest create', () => { sessionToken: r.response.sessionToken, }); }) - .then(r => { + .then((r) => { expect(r.results.length).toEqual(1); const session = r.results[0]; @@ -600,13 +639,13 @@ describe('rest create', () => { done(); }) - .catch(err => { + .catch((err) => { jfail(err); done(); }); }); - it('can create a session with no expiration', done => { + it('can create a session with no expiration', (done) => { const user = { username: 'asdf', password: 'zxcv', @@ -616,7 +655,7 @@ describe('rest create', () => { rest .create(config, auth.nobody(config), '_User', user) - .then(r => { + .then((r) => { expect(Object.keys(r.response).length).toEqual(3); expect(typeof r.response.objectId).toEqual('string'); expect(typeof r.response.createdAt).toEqual('string'); @@ -625,7 +664,7 @@ describe('rest create', () => { sessionToken: r.response.sessionToken, }); }) - .then(r => { + .then((r) => { expect(r.results.length).toEqual(1); const session = r.results[0]; @@ -633,42 +672,42 @@ describe('rest create', () => { done(); }) - .catch(err => { + .catch((err) => { console.error(err); fail(err); done(); }); }); - it('can create object in volatileClasses if masterKey', done => { + it('can create object in volatileClasses if masterKey', (done) => { rest .create(config, auth.master(config), '_PushStatus', {}) - .then(r => { + .then((r) => { expect(r.response.objectId.length).toBe(10); }) .then(() => { - rest.create(config, auth.master(config), '_JobStatus', {}).then(r => { + rest.create(config, auth.master(config), '_JobStatus', {}).then((r) => { expect(r.response.objectId.length).toBe(10); done(); }); }); }); - it('cannot create object in volatileClasses if not masterKey', done => { + it('cannot create object in volatileClasses if not masterKey', (done) => { Promise.resolve() .then(() => { return rest.create(config, auth.nobody(config), '_PushStatus', {}); }) - .catch(error => { + .catch((error) => { expect(error.code).toEqual(119); done(); }); }); - it('locks down session', done => { + it('locks down session', (done) => { let currentUser; Parse.User.signUp('foo', 'bar') - .then(user => { + .then((user) => { currentUser = user; const sessionToken = user.getSessionToken(); const headers = { @@ -682,7 +721,7 @@ describe('rest create', () => { headers: headers, url: 'http://localhost:8378/1/sessions/me', }) - .then(response => { + .then((response) => { sessionId = response.data.objectId; return request({ headers, @@ -693,7 +732,7 @@ describe('rest create', () => { }, }); }) - .then(done.fail, res => { + .then(done.fail, (res) => { expect(res.status).toBe(400); expect(res.data.code).toBe(105); return request({ @@ -705,12 +744,12 @@ describe('rest create', () => { }, }); }) - .then(done.fail, res => { + .then(done.fail, (res) => { expect(res.status).toBe(400); expect(res.data.code).toBe(105); return Parse.User.signUp('other', 'user'); }) - .then(otherUser => { + .then((otherUser) => { const user = new Parse.User(); user.id = otherUser.id; return request({ @@ -722,7 +761,7 @@ describe('rest create', () => { }, }); }) - .then(done.fail, res => { + .then(done.fail, (res) => { expect(res.status).toBe(400); expect(res.data.code).toBe(105); const user = new Parse.User(); @@ -742,10 +781,10 @@ describe('rest create', () => { .catch(done.fail); }); - it('sets current user in new sessions', done => { + it('sets current user in new sessions', (done) => { let currentUser; Parse.User.signUp('foo', 'bar') - .then(user => { + .then((user) => { currentUser = user; const sessionToken = user.getSessionToken(); const headers = { @@ -763,7 +802,7 @@ describe('rest create', () => { }, }); }) - .then(response => { + .then((response) => { if (response.data.user.objectId === currentUser.id) { return done(); } else { @@ -775,7 +814,7 @@ describe('rest create', () => { }); describe('rest update', () => { - it('ignores createdAt', done => { + it('ignores createdAt', (done) => { const config = Config.get('test'); const nobody = auth.nobody(config); const className = 'Foo'; @@ -783,7 +822,7 @@ describe('rest update', () => { rest .create(config, nobody, className, {}) - .then(res => { + .then((res) => { const objectId = res.response.objectId; const restObject = { createdAt: { __type: 'Date', iso: newCreatedAt }, // should be ignored @@ -798,7 +837,7 @@ describe('rest update', () => { return rest.find(config, nobody, className, restWhere, {}); }); }) - .then(res2 => { + .then((res2) => { const updatedObject = res2.results[0]; expect(new Date(updatedObject.createdAt)).not.toEqual(newCreatedAt); done(); @@ -828,7 +867,7 @@ describe('read-only masterKey', () => { }).toThrow(); }); - it('properly blocks writes', done => { + it('properly blocks writes', (done) => { reconfigureServer({ readOnlyMasterKey: 'yolo-read-only', }) @@ -845,7 +884,7 @@ describe('read-only masterKey', () => { }); }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to perform the create operation." @@ -854,13 +893,13 @@ describe('read-only masterKey', () => { }); }); - it('should throw when masterKey and readOnlyMasterKey are the same', done => { + it('should throw when masterKey and readOnlyMasterKey are the same', (done) => { reconfigureServer({ masterKey: 'yolo', readOnlyMasterKey: 'yolo', }) .then(done.fail) - .catch(err => { + .catch((err) => { expect(err).toEqual( new Error('masterKey and readOnlyMasterKey should be different') ); @@ -880,7 +919,7 @@ describe('read-only masterKey', () => { ); }); - it('should throw when trying to create schema', done => { + it('should throw when trying to create schema', (done) => { return request({ method: 'POST', url: `${Parse.serverURL}/schemas`, @@ -892,7 +931,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to create a schema." @@ -901,7 +940,7 @@ describe('read-only masterKey', () => { }); }); - it('should throw when trying to create schema with a name', done => { + it('should throw when trying to create schema with a name', (done) => { return request({ url: `${Parse.serverURL}/schemas/MyClass`, method: 'POST', @@ -913,7 +952,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to create a schema." @@ -922,7 +961,7 @@ describe('read-only masterKey', () => { }); }); - it('should throw when trying to update schema', done => { + it('should throw when trying to update schema', (done) => { return request({ url: `${Parse.serverURL}/schemas/MyClass`, method: 'PUT', @@ -934,7 +973,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to update a schema." @@ -943,7 +982,7 @@ describe('read-only masterKey', () => { }); }); - it('should throw when trying to delete schema', done => { + it('should throw when trying to delete schema', (done) => { return request({ url: `${Parse.serverURL}/schemas/MyClass`, method: 'DELETE', @@ -955,7 +994,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to delete a schema." @@ -964,7 +1003,7 @@ describe('read-only masterKey', () => { }); }); - it('should throw when trying to update the global config', done => { + it('should throw when trying to update the global config', (done) => { return request({ url: `${Parse.serverURL}/config`, method: 'PUT', @@ -976,7 +1015,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to update the config." @@ -985,7 +1024,7 @@ describe('read-only masterKey', () => { }); }); - it('should throw when trying to send push', done => { + it('should throw when trying to send push', (done) => { return request({ url: `${Parse.serverURL}/push`, method: 'POST', @@ -997,7 +1036,7 @@ describe('read-only masterKey', () => { json: {}, }) .then(done.fail) - .catch(res => { + .catch((res) => { expect(res.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN); expect(res.data.error).toBe( "read-only masterKey isn't allowed to send push notifications." From 2f725988767c413bee09650401c76bed0044296d Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 16 Apr 2020 19:19:48 -0400 Subject: [PATCH 3/3] removed comment that wasn't needed --- spec/rest.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/rest.spec.js b/spec/rest.spec.js index 538f1b4cb2..3dd8e1c13f 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -490,7 +490,7 @@ describe('rest create', () => { aPointer: { __type: 'Pointer', className: 'JustThePointer', - objectId: '49F62F92-9B56-46E7-A3D4-BBD14C52F666', // make it 10 chars to match PG storage + objectId: '49F62F92-9B56-46E7-A3D4-BBD14C52F666', }, }; rest