Fix: properly pass req.user to liveQuery triggers (#7296)
This commit is contained in:
@@ -645,6 +645,69 @@ describe('ParseLiveQuery', function () {
|
|||||||
await object.save();
|
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 => {
|
it('handle invalid websocket payload length', async done => {
|
||||||
await reconfigureServer({
|
await reconfigureServer({
|
||||||
liveQuery: {
|
liveQuery: {
|
||||||
|
|||||||
@@ -170,8 +170,10 @@ class ParseLiveQueryServer {
|
|||||||
};
|
};
|
||||||
const trigger = getTrigger(className, 'afterEvent', Parse.applicationId);
|
const trigger = getTrigger(className, 'afterEvent', Parse.applicationId);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
const auth = await this.getAuthForSessionToken(res.sessionToken);
|
const auth = await this.getAuthFromClient(client, requestId);
|
||||||
res.user = auth.user;
|
if (auth && auth.user) {
|
||||||
|
res.user = auth.user;
|
||||||
|
}
|
||||||
if (res.object) {
|
if (res.object) {
|
||||||
res.object = Parse.Object.fromJSON(res.object);
|
res.object = Parse.Object.fromJSON(res.object);
|
||||||
}
|
}
|
||||||
@@ -317,8 +319,10 @@ class ParseLiveQueryServer {
|
|||||||
if (res.original) {
|
if (res.original) {
|
||||||
res.original = Parse.Object.fromJSON(res.original);
|
res.original = Parse.Object.fromJSON(res.original);
|
||||||
}
|
}
|
||||||
const auth = await this.getAuthForSessionToken(res.sessionToken);
|
const auth = await this.getAuthFromClient(client, requestId);
|
||||||
res.user = auth.user;
|
if (auth && auth.user) {
|
||||||
|
res.user = auth.user;
|
||||||
|
}
|
||||||
await runTrigger(trigger, `afterEvent.${className}`, res, auth);
|
await runTrigger(trigger, `afterEvent.${className}`, res, auth);
|
||||||
}
|
}
|
||||||
if (!res.sendEvent) {
|
if (!res.sendEvent) {
|
||||||
@@ -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> {
|
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
|
// Return true directly if ACL isn't present, ACL is public read, or client has master key
|
||||||
if (!acl || acl.getPublicReadAccess() || client.hasMasterKey) {
|
if (!acl || acl.getPublicReadAccess() || client.hasMasterKey) {
|
||||||
@@ -631,8 +653,10 @@ class ParseLiveQueryServer {
|
|||||||
};
|
};
|
||||||
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
|
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
const auth = await this.getAuthForSessionToken(req.sessionToken);
|
const auth = await this.getAuthFromClient(client, request.requestId, req.sessionToken);
|
||||||
req.user = auth.user;
|
if (auth && auth.user) {
|
||||||
|
req.user = auth.user;
|
||||||
|
}
|
||||||
await runTrigger(trigger, `beforeConnect.@Connect`, req, auth);
|
await runTrigger(trigger, `beforeConnect.@Connect`, req, auth);
|
||||||
}
|
}
|
||||||
parseWebsocket.clientId = clientId;
|
parseWebsocket.clientId = clientId;
|
||||||
@@ -690,8 +714,10 @@ class ParseLiveQueryServer {
|
|||||||
try {
|
try {
|
||||||
const trigger = getTrigger(className, 'beforeSubscribe', Parse.applicationId);
|
const trigger = getTrigger(className, 'beforeSubscribe', Parse.applicationId);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
const auth = await this.getAuthForSessionToken(request.sessionToken);
|
const auth = await this.getAuthFromClient(client, request.requestId, request.sessionToken);
|
||||||
request.user = auth.user;
|
if (auth && auth.user) {
|
||||||
|
request.user = auth.user;
|
||||||
|
}
|
||||||
|
|
||||||
const parseQuery = new Parse.Query(className);
|
const parseQuery = new Parse.Query(className);
|
||||||
parseQuery.withJSON(request.query);
|
parseQuery.withJSON(request.query);
|
||||||
|
|||||||
Reference in New Issue
Block a user