Pass context in beforeDelete, afterDelete, beforeFind and Parse.Cloud.run. (#6666)

* add context for following hooks.
1. beforeDelete
2. afterDelete
3. beforeFind
4. Cloud Function

* revert un-necessary code change.

* fix: failing test cases.

* fix: failing test cases.

* fix: failing test cases.

* fix: failing test cases.

* fix: failing test cases.

* fix: failing test cases.

* fix: failing test cases.

* review changes

* revert changes

* revert changes

* review changes

* lint changes

* review changes
This commit is contained in:
yog27ray
2020-07-11 02:17:27 +05:30
committed by GitHub
parent 4437ea73ba
commit 34614e0f78
19 changed files with 130 additions and 43 deletions

View File

@@ -2968,4 +2968,58 @@ describe('afterLogin hook', () => {
obj.set("obj2", obj2);
await obj.save(null, { context: { a: 'a' } });
});
it('should have access to context as saveAll argument', async () => {
Parse.Cloud.beforeSave('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
Parse.Cloud.afterSave('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
const obj1 = new TestObject();
const obj2 = new TestObject();
await Parse.Object.saveAll([obj1, obj2], { context: { a: 'a' }});
});
it('should have access to context as destroyAll argument', async () => {
Parse.Cloud.beforeDelete('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
Parse.Cloud.afterDelete('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
const obj1 = new TestObject();
const obj2 = new TestObject();
await Parse.Object.saveAll([obj1, obj2]);
await Parse.Object.destroyAll([obj1, obj2], { context: { a: 'a' } });
});
it('should have access to context as destroy a object', async () => {
Parse.Cloud.beforeDelete('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
Parse.Cloud.afterDelete('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
const obj = new TestObject();
await obj.save();
await obj.destroy({ context: { a: 'a' } });
});
it('should have access to context in beforeFind hook', async () => {
Parse.Cloud.beforeFind('TestObject', (req) => {
expect(req.context.a).toEqual('a');
});
const query = new Parse.Query('TestObject');
return query.find({ context: { a: 'a' } });
});
it('should have access to context when cloud function is called.', async () => {
Parse.Cloud.define('contextTest', async (req) => {
expect(req.context.a).toEqual('a');
return {};
});
await Parse.Cloud.run('contextTest', {}, { context: { a: 'a' } });
});
});

View File

@@ -5,7 +5,7 @@ const createObject = async (className, fields, config, auth, info) => {
fields = {};
}
return (await rest.create(config, auth, className, fields, info.clientSDK))
return (await rest.create(config, auth, className, fields, info.clientSDK, info.context))
.response;
};
@@ -27,12 +27,13 @@ const updateObject = async (
className,
{ objectId },
fields,
info.clientSDK
info.clientSDK,
info.context
)).response;
};
const deleteObject = async (className, objectId, config, auth, info) => {
await rest.del(config, auth, className, objectId, info.clientSDK);
await rest.del(config, auth, className, objectId, info.context);
return true;
};

View File

@@ -74,7 +74,8 @@ const getObject = async (
className,
objectId,
options,
info.clientSDK
info.clientSDK,
info.context
);
if (!response.results || response.results.length == 0) {
@@ -142,7 +143,8 @@ const findObjects = async (
className,
where,
preCountOptions,
info.clientSDK
info.clientSDK,
info.context
)
).count;
if ((skip || 0) + limit < preCount) {
@@ -222,7 +224,8 @@ const findObjects = async (
className,
where,
options,
info.clientSDK
info.clientSDK,
info.context
);
results = findResult.results;
count = findResult.count;

View File

@@ -55,7 +55,8 @@ const getUserFromSessionToken = async (
'_Session',
{ sessionToken },
options,
info.clientVersion
info.clientVersion,
info.context,
);
if (
!response.results ||

View File

@@ -107,6 +107,7 @@ function ParseServerRESTController(applicationId, router) {
info: {
applicationId: applicationId,
sessionToken: options.sessionToken,
context: options.context || {}, // Add context
},
query,
};

View File

@@ -32,6 +32,7 @@ function RestWrite(
data,
originalData,
clientSDK,
context,
action
) {
if (auth.isReadOnly) {
@@ -46,18 +47,12 @@ function RestWrite(
this.clientSDK = clientSDK;
this.storage = {};
this.runOptions = {};
this.context = {};
this.context = context || {};
if (action) {
this.runOptions.action = action;
}
// Parse context
if (data._context && data._context instanceof Object) {
this.context = data._context;
delete data._context;
}
if (!query) {
if (this.config.allowCustomObjectId) {
if (

View File

@@ -69,7 +69,8 @@ export class AggregateRouter extends ClassesRouter {
this.className(req),
body.where,
options,
req.info.clientSDK
req.info.clientSDK,
req.info.context,
)
.then(response => {
for (const result of response.results) {

View File

@@ -21,7 +21,8 @@ export class AudiencesRouter extends ClassesRouter {
'_Audience',
body.where,
options,
req.info.clientSDK
req.info.clientSDK,
req.info.context,
)
.then(response => {
response.results.forEach(item => {

View File

@@ -40,7 +40,8 @@ export class ClassesRouter extends PromiseRouter {
this.className(req),
body.where,
options,
req.info.clientSDK
req.info.clientSDK,
req.info.context,
)
.then(response => {
return { response: response };
@@ -120,7 +121,8 @@ export class ClassesRouter extends PromiseRouter {
req.auth,
this.className(req),
req.body,
req.info.clientSDK
req.info.clientSDK,
req.info.context
);
}
@@ -132,7 +134,8 @@ export class ClassesRouter extends PromiseRouter {
this.className(req),
where,
req.body,
req.info.clientSDK
req.info.clientSDK,
req.info.context
);
}
@@ -143,7 +146,7 @@ export class ClassesRouter extends PromiseRouter {
req.auth,
this.className(req),
req.params.objectId,
req.info.clientSDK
req.info.context
)
.then(() => {
return { response: {} };

View File

@@ -88,7 +88,8 @@ export class CloudCodeRouter extends PromiseRouter {
req.auth,
'_JobSchedule',
formatJobSchedule(job_schedule),
req.client
req.client,
req.info.context
);
}
@@ -102,7 +103,9 @@ export class CloudCodeRouter extends PromiseRouter {
req.auth,
'_JobSchedule',
{ objectId },
formatJobSchedule(job_schedule)
formatJobSchedule(job_schedule),
undefined,
req.info.context
)
.then(response => {
return {
@@ -114,7 +117,7 @@ export class CloudCodeRouter extends PromiseRouter {
static deleteJob(req) {
const { objectId } = req.params;
return rest
.del(req.config, req.auth, '_JobSchedule', objectId)
.del(req.config, req.auth, '_JobSchedule', objectId, req.info.context)
.then(response => {
return {
response,

View File

@@ -148,6 +148,7 @@ export class FunctionsRouter extends PromiseRouter {
headers: req.config.headers,
ip: req.config.ip,
functionName,
context: req.info.context,
};
if (theValidator && typeof theValidator === 'function') {

View File

@@ -51,7 +51,8 @@ function getFileForProductIdentifier(productIdentifier, req) {
'_Product',
{ productIdentifier: productIdentifier },
undefined,
req.info.clientSDK
req.info.clientSDK,
req.info.context
)
.then(function(result) {
const products = result.results;

View File

@@ -21,7 +21,8 @@ export class InstallationsRouter extends ClassesRouter {
'_Installation',
body.where,
options,
req.info.clientSDK
req.info.clientSDK,
req.info.context
)
.then(response => {
return { response: response };

View File

@@ -23,7 +23,8 @@ export class SessionsRouter extends ClassesRouter {
'_Session',
{ sessionToken: req.info.sessionToken },
undefined,
req.info.clientSDK
req.info.clientSDK,
req.info.context
)
.then(response => {
if (!response.results || response.results.length == 0) {

View File

@@ -178,7 +178,8 @@ export class UsersRouter extends ClassesRouter {
'_Session',
{ sessionToken },
{ include: 'user' },
req.info.clientSDK
req.info.clientSDK,
req.info.context
)
.then(response => {
if (
@@ -302,7 +303,8 @@ export class UsersRouter extends ClassesRouter {
'_Session',
{ sessionToken: req.info.sessionToken },
undefined,
req.info.clientSDK
req.info.clientSDK,
req.info.context
)
.then(records => {
if (records.results && records.results.length) {
@@ -311,7 +313,8 @@ export class UsersRouter extends ClassesRouter {
req.config,
Auth.master(req.config),
'_Session',
records.results[0].objectId
records.results[0].objectId,
req.info.context
)
.then(() => {
this._runAfterLogoutTrigger(req, records.results[0]);

View File

@@ -100,9 +100,6 @@ function handleBatch(router, req) {
info: req.info,
};
// Add context to request body
if (req.body._context) { request.body._context = req.body._context; }
return router
.tryRouteRequest(restRequest.method, routablePath, request)
.then(

View File

@@ -33,6 +33,7 @@ export function handleParseHeaders(req, res, next) {
dotNetKey: req.get('X-Parse-Windows-Key'),
restAPIKey: req.get('X-Parse-REST-API-Key'),
clientVersion: req.get('X-Parse-Client-Version'),
context: {},
};
var basicAuth = httpAuth(req);
@@ -103,6 +104,10 @@ export function handleParseHeaders(req, res, next) {
info.masterKey = req.body._MasterKey;
delete req.body._MasterKey;
}
if (req.body._context && req.body._context instanceof Object) {
info.context = req.body._context;
delete req.body._context;
}
if (req.body._ContentType) {
req.headers['content-type'] = req.body._ContentType;
delete req.body._ContentType;

View File

@@ -31,7 +31,7 @@ function checkLiveQuery(className, config) {
}
// Returns a promise for an object with optional keys 'results' and 'count'.
function find(config, auth, className, restWhere, restOptions, clientSDK) {
function find(config, auth, className, restWhere, restOptions, clientSDK, context) {
enforceRoleSecurity('find', className, auth);
return triggers
.maybeRunQueryTrigger(
@@ -40,7 +40,8 @@ function find(config, auth, className, restWhere, restOptions, clientSDK) {
restWhere,
restOptions,
config,
auth
auth,
context
)
.then(result => {
restWhere = result.restWhere || restWhere;
@@ -58,7 +59,7 @@ function find(config, auth, className, restWhere, restOptions, clientSDK) {
}
// get is just like find but only queries an objectId.
const get = (config, auth, className, objectId, restOptions, clientSDK) => {
const get = (config, auth, className, objectId, restOptions, clientSDK, context) => {
var restWhere = { objectId };
enforceRoleSecurity('get', className, auth);
return triggers
@@ -69,6 +70,7 @@ const get = (config, auth, className, objectId, restOptions, clientSDK) => {
restOptions,
config,
auth,
context,
true
)
.then(result => {
@@ -87,7 +89,7 @@ const get = (config, auth, className, objectId, restOptions, clientSDK) => {
};
// Returns a promise that doesn't resolve to any useful value.
function del(config, auth, className, objectId) {
function del(config, auth, className, objectId, context) {
if (typeof objectId !== 'string') {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad objectId');
}
@@ -134,7 +136,8 @@ function del(config, auth, className, objectId) {
auth,
inflatedObject,
null,
config
config,
context
);
}
throw new Parse.Error(
@@ -187,7 +190,8 @@ function del(config, auth, className, objectId) {
auth,
inflatedObject,
null,
config
config,
context
);
})
.catch(error => {
@@ -196,7 +200,7 @@ function del(config, auth, className, objectId) {
}
// Returns a promise for a {response, status, location} object.
function create(config, auth, className, restObject, clientSDK) {
function create(config, auth, className, restObject, clientSDK, context) {
enforceRoleSecurity('create', className, auth);
var write = new RestWrite(
config,
@@ -205,7 +209,8 @@ function create(config, auth, className, restObject, clientSDK) {
null,
restObject,
null,
clientSDK
clientSDK,
context
);
return write.execute();
}
@@ -213,7 +218,7 @@ function create(config, auth, className, restObject, clientSDK) {
// Returns a promise that contains the fields of the update that the
// REST API is supposed to return.
// Usually, this is just updatedAt.
function update(config, auth, className, restWhere, restObject, clientSDK) {
function update(config, auth, className, restWhere, restObject, clientSDK, context) {
enforceRoleSecurity('update', className, auth);
return Promise.resolve()
@@ -252,6 +257,7 @@ function update(config, auth, className, restWhere, restObject, clientSDK) {
restObject,
originalRestObject,
clientSDK,
context,
'update'
).execute();
})

View File

@@ -233,7 +233,10 @@ export function getRequestObject(
request.original = originalParseObject;
}
if (triggerType === Types.beforeSave || triggerType === Types.afterSave) {
if (triggerType === Types.beforeSave ||
triggerType === Types.afterSave ||
triggerType === Types.beforeDelete ||
triggerType === Types.afterDelete) {
// Set a copy of the context on the request object.
request.context = Object.assign({}, context);
}
@@ -259,6 +262,7 @@ export function getRequestQueryObject(
query,
count,
config,
context,
isGet
) {
isGet = !!isGet;
@@ -272,6 +276,7 @@ export function getRequestQueryObject(
isGet,
headers: config.headers,
ip: config.ip,
context: context || {},
};
if (!auth) {
@@ -460,6 +465,7 @@ export function maybeRunQueryTrigger(
restOptions,
config,
auth,
context,
isGet
) {
const trigger = getTrigger(className, triggerType, config.applicationId);
@@ -485,6 +491,7 @@ export function maybeRunQueryTrigger(
parseQuery,
count,
config,
context,
isGet
);
return Promise.resolve()
@@ -605,7 +612,9 @@ export function maybeRunTrigger(
);
if (
triggerType === Types.beforeSave ||
triggerType === Types.afterSave
triggerType === Types.afterSave ||
triggerType === Types.beforeDelete ||
triggerType === Types.afterDelete
) {
Object.assign(context, request.context);
}