From 5743d752f7b66a2376793f832339bf07e277811c Mon Sep 17 00:00:00 2001
From: dblythy <daniel-blyth@live.com.au>
Date: Wed, 26 Aug 2020 00:35:48 +1000
Subject: [PATCH] Fix mutating beforeSubscribe Query (#6868)

* Fix beforeSubscribe

* Remove return value
---
 spec/ParseLiveQuery.spec.js | 89 +++++++++++++++++++++++++++++++++++++
 src/triggers.js             |  7 ++-
 2 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js
index 80eebaa733..5e2321229f 100644
--- a/spec/ParseLiveQuery.spec.js
+++ b/spec/ParseLiveQuery.spec.js
@@ -115,6 +115,95 @@ describe('ParseLiveQuery', function () {
     });
   });
 
+  it('can handle mutate beforeSubscribe query', async done => {
+    await reconfigureServer({
+      liveQuery: {
+        classNames: ['TestObject'],
+      },
+      startLiveQueryServer: true,
+      verbose: false,
+      silent: true,
+    });
+    Parse.Cloud.beforeSubscribe(TestObject, request => {
+      const query = request.query;
+      query.equalTo('yolo', 'abc');
+    });
+
+    const object = new TestObject();
+    await object.save();
+
+    const query = new Parse.Query(TestObject);
+    query.equalTo('objectId', object.id);
+    const subscription = await query.subscribe();
+
+    subscription.on('update', () => {
+      fail();
+    });
+    object.set({ foo: 'bar' });
+    await object.save();
+    setTimeout(async () => {
+      done();
+    }, 1000);
+  });
+
+  it('can return a new beforeSubscribe query', async done => {
+    await reconfigureServer({
+      liveQuery: {
+        classNames: ['TestObject'],
+      },
+      startLiveQueryServer: true,
+      verbose: false,
+      silent: true,
+    });
+    Parse.Cloud.beforeSubscribe(TestObject, request => {
+      const query = new Parse.Query(TestObject);
+      query.equalTo('foo', 'yolo');
+      request.query = query;
+    });
+
+    const query = new Parse.Query(TestObject);
+    query.equalTo('foo', 'bar');
+    const subscription = await query.subscribe();
+
+    subscription.on('create', object => {
+      expect(object.get('foo')).toBe('yolo');
+      done();
+    });
+    const object = new TestObject();
+    object.set({ foo: 'yolo' });
+    await object.save();
+  });
+
+  it('can handle select beforeSubscribe query', async done => {
+    await reconfigureServer({
+      liveQuery: {
+        classNames: ['TestObject'],
+      },
+      startLiveQueryServer: true,
+      verbose: false,
+      silent: true,
+    });
+    Parse.Cloud.beforeSubscribe(TestObject, request => {
+      const query = request.query;
+      query.select('yolo');
+    });
+
+    const object = new TestObject();
+    await object.save();
+
+    const query = new Parse.Query(TestObject);
+    query.equalTo('objectId', object.id);
+    const subscription = await query.subscribe();
+
+    subscription.on('update', object => {
+      expect(object.get('foo')).toBeUndefined();
+      expect(object.get('yolo')).toBe('abc');
+      done();
+    });
+    object.set({ foo: 'bar', yolo: 'abc' });
+    await object.save();
+  });
+
   it('handle invalid websocket payload length', async done => {
     await reconfigureServer({
       liveQuery: {
diff --git a/src/triggers.js b/src/triggers.js
index 96dcb65e47..de9856841e 100644
--- a/src/triggers.js
+++ b/src/triggers.js
@@ -794,7 +794,12 @@ export async function maybeRunSubscribeTrigger(
   parseQuery.withJSON(request.query);
   request.query = parseQuery;
   request.user = await userForSessionToken(request.sessionToken);
-  return trigger(request);
+  await trigger(request);
+  const query = request.query.toJSON();
+  if (query.keys) {
+    query.fields = query.keys.split(',');
+  }
+  request.query = query;
 }
 
 async function userForSessionToken(sessionToken) {