Skip to content

Commit

Permalink
Fix: properly pass req.user to liveQuery triggers (parse-community#7296)
Browse files Browse the repository at this point in the history
  • Loading branch information
dblythy authored May 2, 2021
1 parent e9f54e2 commit 51e0800
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 8 deletions.
63 changes: 63 additions & 0 deletions spec/ParseLiveQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,69 @@ describe('ParseLiveQuery', function () {
await object.save();
});

it('LiveQuery with ACL', async () => {
await reconfigureServer({
liveQuery: {
classNames: ['Chat'],
},
startLiveQueryServer: true,
verbose: false,
silent: true,
});
const user = new Parse.User();
user.setUsername('username');
user.setPassword('password');
await user.signUp();

const calls = {
beforeConnect(req) {
expect(req.event).toBe('connect');
expect(req.clients).toBe(0);
expect(req.subscriptions).toBe(0);
expect(req.useMasterKey).toBe(false);
expect(req.installationId).toBeDefined();
expect(req.client).toBeDefined();
},
beforeSubscribe(req) {
expect(req.op).toBe('subscribe');
expect(req.requestId).toBe(1);
expect(req.query).toBeDefined();
expect(req.user).toBeDefined();
},
afterLiveQueryEvent(req) {
expect(req.user).toBeDefined();
expect(req.object.get('foo')).toBe('bar');
},
create(object) {
expect(object.get('foo')).toBe('bar');
},
delete(object) {
expect(object.get('foo')).toBe('bar');
},
};
for (const key in calls) {
spyOn(calls, key).and.callThrough();
}
Parse.Cloud.beforeConnect(calls.beforeConnect);
Parse.Cloud.beforeSubscribe('Chat', calls.beforeSubscribe);
Parse.Cloud.afterLiveQueryEvent('Chat', calls.afterLiveQueryEvent);

const chatQuery = new Parse.Query('Chat');
const subscription = await chatQuery.subscribe();
subscription.on('create', calls.create);
subscription.on('delete', calls.delete);
const object = new Parse.Object('Chat');
const acl = new Parse.ACL(user);
object.setACL(acl);
object.set({ foo: 'bar' });
await object.save();
await object.destroy();
await new Promise(resolve => setTimeout(resolve, 200));
for (const key in calls) {
expect(calls[key]).toHaveBeenCalled();
}
});

it('handle invalid websocket payload length', async done => {
await reconfigureServer({
liveQuery: {
Expand Down
42 changes: 34 additions & 8 deletions src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,10 @@ class ParseLiveQueryServer {
};
const trigger = getTrigger(className, 'afterEvent', Parse.applicationId);
if (trigger) {
const auth = await this.getAuthForSessionToken(res.sessionToken);
res.user = auth.user;
const auth = await this.getAuthFromClient(client, requestId);
if (auth && auth.user) {
res.user = auth.user;
}
if (res.object) {
res.object = Parse.Object.fromJSON(res.object);
}
Expand Down Expand Up @@ -317,8 +319,10 @@ class ParseLiveQueryServer {
if (res.original) {
res.original = Parse.Object.fromJSON(res.original);
}
const auth = await this.getAuthForSessionToken(res.sessionToken);
res.user = auth.user;
const auth = await this.getAuthFromClient(client, requestId);
if (auth && auth.user) {
res.user = auth.user;
}
await runTrigger(trigger, `afterEvent.${className}`, res, auth);
}
if (!res.sendEvent) {
Expand Down Expand Up @@ -579,6 +583,24 @@ class ParseLiveQueryServer {
});
}

async getAuthFromClient(client: any, requestId: number, sessionToken: string) {
const getSessionFromClient = () => {
const subscriptionInfo = client.getSubscriptionInfo(requestId);
if (typeof subscriptionInfo === 'undefined') {
return client.sessionToken;
}
return subscriptionInfo.sessionToken || client.sessionToken;
};
if (!sessionToken) {
sessionToken = getSessionFromClient();
}
if (!sessionToken) {
return;
}
const { auth } = await this.getAuthForSessionToken(sessionToken);
return auth;
}

async _matchesACL(acl: any, client: any, requestId: number): Promise<boolean> {
// Return true directly if ACL isn't present, ACL is public read, or client has master key
if (!acl || acl.getPublicReadAccess() || client.hasMasterKey) {
Expand Down Expand Up @@ -631,8 +653,10 @@ class ParseLiveQueryServer {
};
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
if (trigger) {
const auth = await this.getAuthForSessionToken(req.sessionToken);
req.user = auth.user;
const auth = await this.getAuthFromClient(client, request.requestId, req.sessionToken);
if (auth && auth.user) {
req.user = auth.user;
}
await runTrigger(trigger, `beforeConnect.@Connect`, req, auth);
}
parseWebsocket.clientId = clientId;
Expand Down Expand Up @@ -690,8 +714,10 @@ class ParseLiveQueryServer {
try {
const trigger = getTrigger(className, 'beforeSubscribe', Parse.applicationId);
if (trigger) {
const auth = await this.getAuthForSessionToken(request.sessionToken);
request.user = auth.user;
const auth = await this.getAuthFromClient(client, request.requestId, request.sessionToken);
if (auth && auth.user) {
request.user = auth.user;
}

const parseQuery = new Parse.Query(className);
parseQuery.withJSON(request.query);
Expand Down

0 comments on commit 51e0800

Please sign in to comment.