Skip to content

Commit cba81dd

Browse files
committed
revoke triggers
1 parent 00389d1 commit cba81dd

File tree

3 files changed

+195
-210
lines changed

3 files changed

+195
-210
lines changed

src/LiveQuery/ParseLiveQueryServer.js

Lines changed: 165 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ import { ParsePubSub } from './ParsePubSub';
1010
import SchemaController from '../Controllers/SchemaController';
1111
import _ from 'lodash';
1212
import { v4 as uuidv4 } from 'uuid';
13-
import {
14-
runLiveQueryEventHandlers,
15-
maybeRunConnectTrigger,
16-
maybeRunSubscribeTrigger,
17-
maybeRunAfterEventTrigger,
18-
} from '../triggers';
13+
import { runLiveQueryEventHandlers, getTrigger, runTrigger } from '../triggers';
1914
import { getAuthForSessionToken, Auth } from '../Auth';
2015
import { getCacheController } from '../Controllers';
2116
import LRU from 'lru-cache';
@@ -121,7 +116,7 @@ class ParseLiveQueryServer {
121116

122117
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
123118
// Message.originalParseObject is the original ParseObject.
124-
_onAfterDelete(message: any): void {
119+
async _onAfterDelete(message: any): void {
125120
logger.verbose(Parse.applicationId + 'afterDelete is triggered');
126121

127122
let deletedParseObject = message.currentParseObject.toJSON();
@@ -135,6 +130,7 @@ class ParseLiveQueryServer {
135130
logger.debug('Can not find subscriptions under this class ' + className);
136131
return;
137132
}
133+
138134
for (const subscription of classSubscriptions.values()) {
139135
const isSubscriptionMatched = this._matchesSubscription(deletedParseObject, subscription);
140136
if (!isSubscriptionMatched) {
@@ -150,58 +146,66 @@ class ParseLiveQueryServer {
150146
// Check CLP
151147
const op = this._getCLPOperation(subscription.query);
152148
let res = {};
153-
this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op)
154-
.then(() => {
155-
// Check ACL
156-
return this._matchesACL(acl, client, requestId);
157-
})
158-
.then(isMatched => {
159-
if (!isMatched) {
160-
return null;
161-
}
162-
res = {
163-
event: 'delete',
164-
sessionToken: client.sessionToken,
165-
object: deletedParseObject,
166-
clients: this.clients.size,
167-
subscriptions: this.subscriptions.size,
168-
useMasterKey: client.hasMasterKey,
169-
installationId: client.installationId,
170-
sendEvent: true,
171-
};
172-
return maybeRunAfterEventTrigger('afterEvent', className, res);
173-
})
174-
.then(() => {
175-
if (!res.sendEvent) {
176-
return;
177-
}
178-
if (res.object && typeof res.object.toJSON === 'function') {
179-
deletedParseObject = res.object.toJSON();
180-
deletedParseObject.className = className;
149+
try {
150+
await this._matchesCLP(
151+
classLevelPermissions,
152+
message.currentParseObject,
153+
client,
154+
requestId,
155+
op
156+
);
157+
const isMatched = await this._matchesACL(acl, client, requestId);
158+
if (!isMatched) {
159+
return null;
160+
}
161+
res = {
162+
event: 'delete',
163+
sessionToken: client.sessionToken,
164+
object: deletedParseObject,
165+
clients: this.clients.size,
166+
subscriptions: this.subscriptions.size,
167+
useMasterKey: client.hasMasterKey,
168+
installationId: client.installationId,
169+
sendEvent: true,
170+
};
171+
const trigger = getTrigger(className, 'afterEvent', Parse.applicationId);
172+
if (trigger) {
173+
const auth = await this.getAuthForSessionToken(res.sessionToken);
174+
res.user = auth.user;
175+
if (res.object) {
176+
res.object = Parse.Object.fromJSON(res.object);
181177
}
182-
client.pushDelete(requestId, deletedParseObject);
183-
})
184-
.catch(error => {
185-
Client.pushError(
186-
client.parseWebSocket,
187-
error.code || 141,
188-
error.message || error,
189-
false,
190-
requestId
191-
);
192-
logger.error(
193-
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
194-
JSON.stringify(error)
195-
);
196-
});
178+
await runTrigger(trigger, `afterEvent.${className}`, res, auth);
179+
}
180+
if (!res.sendEvent) {
181+
return;
182+
}
183+
if (res.object && typeof res.object.toJSON === 'function') {
184+
deletedParseObject = res.object.toJSON();
185+
deletedParseObject.className = className;
186+
}
187+
client.pushDelete(requestId, deletedParseObject);
188+
} catch (error) {
189+
Client.pushError(
190+
client.parseWebSocket,
191+
error.code || 141,
192+
error.message || error,
193+
false,
194+
requestId
195+
);
196+
logger.error(
197+
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
198+
JSON.stringify(error)
199+
);
200+
}
197201
}
198202
}
199203
}
200204
}
201205

202206
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
203207
// Message.originalParseObject is the original ParseObject.
204-
_onAfterSave(message: any): void {
208+
async _onAfterSave(message: any): void {
205209
logger.verbose(Parse.applicationId + 'afterSave is triggered');
206210

207211
let originalParseObject = null;
@@ -256,85 +260,98 @@ class ParseLiveQueryServer {
256260
const currentACL = message.currentParseObject.getACL();
257261
currentACLCheckingPromise = this._matchesACL(currentACL, client, requestId);
258262
}
259-
const op = this._getCLPOperation(subscription.query);
260-
this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op)
261-
.then(() => {
262-
return Promise.all([originalACLCheckingPromise, currentACLCheckingPromise]);
263-
})
264-
.then(([isOriginalMatched, isCurrentMatched]) => {
265-
logger.verbose(
266-
'Original %j | Current %j | Match: %s, %s, %s, %s | Query: %s',
267-
originalParseObject,
268-
currentParseObject,
269-
isOriginalSubscriptionMatched,
270-
isCurrentSubscriptionMatched,
271-
isOriginalMatched,
272-
isCurrentMatched,
273-
subscription.hash
274-
);
275-
// Decide event type
276-
let type;
277-
if (isOriginalMatched && isCurrentMatched) {
278-
type = 'update';
279-
} else if (isOriginalMatched && !isCurrentMatched) {
280-
type = 'leave';
281-
} else if (!isOriginalMatched && isCurrentMatched) {
282-
if (originalParseObject) {
283-
type = 'enter';
284-
} else {
285-
type = 'create';
286-
}
263+
try {
264+
const op = this._getCLPOperation(subscription.query);
265+
await this._matchesCLP(
266+
classLevelPermissions,
267+
message.currentParseObject,
268+
client,
269+
requestId,
270+
op
271+
);
272+
const [isOriginalMatched, isCurrentMatched] = await Promise.all([
273+
originalACLCheckingPromise,
274+
currentACLCheckingPromise,
275+
]);
276+
logger.verbose(
277+
'Original %j | Current %j | Match: %s, %s, %s, %s | Query: %s',
278+
originalParseObject,
279+
currentParseObject,
280+
isOriginalSubscriptionMatched,
281+
isCurrentSubscriptionMatched,
282+
isOriginalMatched,
283+
isCurrentMatched,
284+
subscription.hash
285+
);
286+
// Decide event type
287+
let type;
288+
if (isOriginalMatched && isCurrentMatched) {
289+
type = 'update';
290+
} else if (isOriginalMatched && !isCurrentMatched) {
291+
type = 'leave';
292+
} else if (!isOriginalMatched && isCurrentMatched) {
293+
if (originalParseObject) {
294+
type = 'enter';
287295
} else {
288-
return null;
296+
type = 'create';
289297
}
290-
message.event = type;
291-
res = {
292-
event: type,
293-
sessionToken: client.sessionToken,
294-
object: currentParseObject,
295-
original: originalParseObject,
296-
clients: this.clients.size,
297-
subscriptions: this.subscriptions.size,
298-
useMasterKey: client.hasMasterKey,
299-
installationId: client.installationId,
300-
sendEvent: true,
301-
};
302-
return maybeRunAfterEventTrigger('afterEvent', className, res);
303-
})
304-
.then(
305-
() => {
306-
if (!res.sendEvent) {
307-
return;
308-
}
309-
if (res.object && typeof res.object.toJSON === 'function') {
310-
currentParseObject = res.object.toJSON();
311-
currentParseObject.className = res.object.className || className;
312-
}
313-
314-
if (res.original && typeof res.original.toJSON === 'function') {
315-
originalParseObject = res.original.toJSON();
316-
originalParseObject.className = res.original.className || className;
317-
}
318-
const functionName =
319-
'push' + message.event.charAt(0).toUpperCase() + message.event.slice(1);
320-
if (client[functionName]) {
321-
client[functionName](requestId, currentParseObject, originalParseObject);
322-
}
323-
},
324-
error => {
325-
Client.pushError(
326-
client.parseWebSocket,
327-
error.code || 141,
328-
error.message || error,
329-
false,
330-
requestId
331-
);
332-
logger.error(
333-
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
334-
JSON.stringify(error)
335-
);
298+
} else {
299+
return null;
300+
}
301+
message.event = type;
302+
res = {
303+
event: type,
304+
sessionToken: client.sessionToken,
305+
object: currentParseObject,
306+
original: originalParseObject,
307+
clients: this.clients.size,
308+
subscriptions: this.subscriptions.size,
309+
useMasterKey: client.hasMasterKey,
310+
installationId: client.installationId,
311+
sendEvent: true,
312+
};
313+
const trigger = getTrigger(className, 'afterEvent', Parse.applicationId);
314+
if (trigger) {
315+
if (res.object) {
316+
res.object = Parse.Object.fromJSON(res.object);
317+
}
318+
if (res.original) {
319+
res.original = Parse.Object.fromJSON(res.original);
336320
}
321+
const auth = await this.getAuthForSessionToken(res.sessionToken);
322+
res.user = auth.user;
323+
await runTrigger(trigger, `afterEvent.${className}`, res, auth);
324+
}
325+
if (!res.sendEvent) {
326+
return;
327+
}
328+
if (res.object && typeof res.object.toJSON === 'function') {
329+
currentParseObject = res.object.toJSON();
330+
currentParseObject.className = res.object.className || className;
331+
}
332+
333+
if (res.original && typeof res.original.toJSON === 'function') {
334+
originalParseObject = res.original.toJSON();
335+
originalParseObject.className = res.original.className || className;
336+
}
337+
const functionName =
338+
'push' + message.event.charAt(0).toUpperCase() + message.event.slice(1);
339+
if (client[functionName]) {
340+
client[functionName](requestId, currentParseObject, originalParseObject);
341+
}
342+
} catch (error) {
343+
Client.pushError(
344+
client.parseWebSocket,
345+
error.code || 141,
346+
error.message || error,
347+
false,
348+
requestId
349+
);
350+
logger.error(
351+
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
352+
JSON.stringify(error)
337353
);
354+
}
338355
}
339356
}
340357
}
@@ -614,7 +631,12 @@ class ParseLiveQueryServer {
614631
useMasterKey: client.hasMasterKey,
615632
installationId: request.installationId,
616633
};
617-
await maybeRunConnectTrigger('beforeConnect', req);
634+
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
635+
if (trigger) {
636+
const auth = await this.getAuthForSessionToken(req.sessionToken);
637+
req.user = auth.user;
638+
await runTrigger(trigger, `beforeConnect.@Connect`, req, auth);
639+
}
618640
parseWebsocket.clientId = clientId;
619641
this.clients.set(parseWebsocket.clientId, client);
620642
logger.info(`Create new client: ${parseWebsocket.clientId}`);
@@ -668,7 +690,22 @@ class ParseLiveQueryServer {
668690
const client = this.clients.get(parseWebsocket.clientId);
669691
const className = request.query.className;
670692
try {
671-
await maybeRunSubscribeTrigger('beforeSubscribe', className, request);
693+
const trigger = getTrigger(className, 'beforeSubscribe', Parse.applicationId);
694+
if (trigger) {
695+
const auth = await this.getAuthForSessionToken(request.sessionToken);
696+
request.user = auth.user;
697+
698+
const parseQuery = new Parse.Query(className);
699+
parseQuery.withJSON(request.query);
700+
request.query = parseQuery;
701+
await runTrigger(trigger, `beforeSubscribe.${className}`, request, auth);
702+
703+
const query = request.query.toJSON();
704+
if (query.keys) {
705+
query.fields = query.keys.split(',');
706+
}
707+
request.query = query;
708+
}
672709

673710
// Get subscription from subscriptions, create one if necessary
674711
const subscriptionHash = queryHash(request.query);

src/Routers/FunctionsRouter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export class FunctionsRouter extends PromiseRouter {
173173
);
174174
return Promise.resolve()
175175
.then(() => {
176-
return triggers.maybeRunValidator(request, functionName);
176+
return triggers.maybeRunValidator(request, functionName, req.auth);
177177
})
178178
.then(() => {
179179
return theFunction(request);

0 commit comments

Comments
 (0)