skipWithMasterKey on Built-In Validator (#6972)
* Initial Commit * Change to resolveMasterKey * Change to skipWithMasterKey
This commit is contained in:
@@ -554,6 +554,131 @@ describe('cloud validator', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('basic beforeSave skipWithMasterKey', async function (done) {
|
||||
Parse.Cloud.beforeSave(
|
||||
'BeforeSave',
|
||||
() => {
|
||||
throw 'before save should have resolved using masterKey.';
|
||||
},
|
||||
{
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
const obj = new Parse.Object('BeforeSave');
|
||||
obj.set('foo', 'bar');
|
||||
await obj.save(null, { useMasterKey: true });
|
||||
expect(obj.get('foo')).toBe('bar');
|
||||
done();
|
||||
});
|
||||
|
||||
it('basic beforeFind skipWithMasterKey', async function (done) {
|
||||
Parse.Cloud.beforeFind(
|
||||
'beforeFind',
|
||||
() => {
|
||||
throw 'before find should have resolved using masterKey.';
|
||||
},
|
||||
{
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
const obj = new Parse.Object('beforeFind');
|
||||
obj.set('foo', 'bar');
|
||||
await obj.save();
|
||||
expect(obj.get('foo')).toBe('bar');
|
||||
|
||||
const query = new Parse.Query('beforeFind');
|
||||
try {
|
||||
const first = await query.first({ useMasterKey: true });
|
||||
expect(first).toBeDefined();
|
||||
expect(first.id).toBe(obj.id);
|
||||
done();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(e.code);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('basic beforeDelete skipWithMasterKey', async function (done) {
|
||||
Parse.Cloud.beforeDelete(
|
||||
'beforeFind',
|
||||
() => {
|
||||
throw 'before find should have resolved using masterKey.';
|
||||
},
|
||||
{
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
const obj = new Parse.Object('beforeFind');
|
||||
obj.set('foo', 'bar');
|
||||
await obj.save();
|
||||
expect(obj.get('foo')).toBe('bar');
|
||||
await obj.destroy({ useMasterKey: true });
|
||||
done();
|
||||
});
|
||||
|
||||
it('basic beforeSaveFile skipWithMasterKey', async done => {
|
||||
Parse.Cloud.beforeSaveFile(
|
||||
() => {
|
||||
throw 'beforeSaveFile should have resolved using master key.';
|
||||
},
|
||||
{
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
|
||||
const result = await file.save({ useMasterKey: true });
|
||||
expect(result).toBe(file);
|
||||
done();
|
||||
});
|
||||
|
||||
it('beforeSave validateMasterKey and skipWithMasterKey fail', async function (done) {
|
||||
Parse.Cloud.beforeSave(
|
||||
'BeforeSave',
|
||||
() => {
|
||||
throw 'beforeSaveFile should have resolved using master key.';
|
||||
},
|
||||
{
|
||||
fields: ['foo'],
|
||||
validateMasterKey: true,
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
|
||||
const obj = new Parse.Object('BeforeSave');
|
||||
try {
|
||||
await obj.save(null, { useMasterKey: true });
|
||||
fail('function should have failed.');
|
||||
} catch (error) {
|
||||
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
||||
expect(error.message).toEqual('Validation failed. Please specify data for foo.');
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('beforeSave validateMasterKey and skipWithMasterKey success', async function (done) {
|
||||
Parse.Cloud.beforeSave(
|
||||
'BeforeSave',
|
||||
() => {
|
||||
throw 'beforeSaveFile should have resolved using master key.';
|
||||
},
|
||||
{
|
||||
fields: ['foo'],
|
||||
validateMasterKey: true,
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
|
||||
const obj = new Parse.Object('BeforeSave');
|
||||
obj.set('foo', 'bar');
|
||||
try {
|
||||
await obj.save(null, { useMasterKey: true });
|
||||
done();
|
||||
} catch (error) {
|
||||
fail('error should not have been called.');
|
||||
}
|
||||
});
|
||||
|
||||
it('basic beforeSave requireUserKey on User Class', async function (done) {
|
||||
Parse.Cloud.beforeSave(Parse.User, () => {}, {
|
||||
requireUser: true,
|
||||
|
||||
@@ -122,6 +122,24 @@ describe('Cloud Code', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('beforeFind can throw string', async function (done) {
|
||||
Parse.Cloud.beforeFind('beforeFind', () => {
|
||||
throw 'throw beforeFind';
|
||||
});
|
||||
const obj = new Parse.Object('beforeFind');
|
||||
obj.set('foo', 'bar');
|
||||
await obj.save();
|
||||
expect(obj.get('foo')).toBe('bar');
|
||||
try {
|
||||
const query = new Parse.Query('beforeFind');
|
||||
await query.first();
|
||||
} catch (e) {
|
||||
expect(e.code).toBe(141);
|
||||
expect(e.message).toBe('throw beforeFind');
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('beforeSave rejection with custom error code', function (done) {
|
||||
Parse.Cloud.beforeSave('BeforeSaveFailWithErrorCode', function () {
|
||||
throw new Parse.Error(999, 'Nope');
|
||||
@@ -1894,7 +1912,7 @@ describe('beforeFind hooks', () => {
|
||||
done();
|
||||
},
|
||||
err => {
|
||||
expect(err.code).toBe(1);
|
||||
expect(err.code).toBe(141);
|
||||
expect(err.message).toEqual('Do not run that query');
|
||||
done();
|
||||
}
|
||||
|
||||
@@ -712,6 +712,7 @@ module.exports = ParseCloud;
|
||||
* @property {Boolean} requireUser whether the cloud trigger requires a user.
|
||||
* @property {Boolean} requireMaster whether the cloud trigger requires a master key.
|
||||
* @property {Boolean} validateMasterKey whether the validator should run if masterKey is provided. Defaults to false.
|
||||
* @property {Boolean} skipWithMasterKey whether the cloud code function should be ignored using a masterKey.
|
||||
*
|
||||
* @property {Array<String>|Object} requireUserKeys If set, keys required on request.user to make the request.
|
||||
* @property {String} requireUserKeys.field If requireUserKeys is an object, name of field to validate on request user
|
||||
|
||||
@@ -331,13 +331,11 @@ export function getResponseObject(request, resolve, reject) {
|
||||
return resolve(response);
|
||||
},
|
||||
error: function (error) {
|
||||
if (error instanceof Parse.Error) {
|
||||
reject(error);
|
||||
} else if (error instanceof Error) {
|
||||
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error.message));
|
||||
} else {
|
||||
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error));
|
||||
}
|
||||
const e = resolveError(error, {
|
||||
code: Parse.Error.SCRIPT_FAILED,
|
||||
message: 'Script failed. Unknown error.',
|
||||
});
|
||||
reject(e);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -420,6 +418,9 @@ export function maybeRunAfterFindTrigger(triggerType, auth, className, objects,
|
||||
return maybeRunValidator(request, `${triggerType}.${className}`);
|
||||
})
|
||||
.then(() => {
|
||||
if (request.skipWithMasterKey) {
|
||||
return request.objects;
|
||||
}
|
||||
const response = trigger(request);
|
||||
if (response && typeof response.then === 'function') {
|
||||
return response.then(results => {
|
||||
@@ -482,6 +483,9 @@ export function maybeRunQueryTrigger(
|
||||
return maybeRunValidator(requestObject, `${triggerType}.${className}`);
|
||||
})
|
||||
.then(() => {
|
||||
if (requestObject.skipWithMasterKey) {
|
||||
return requestObject.query;
|
||||
}
|
||||
return trigger(requestObject);
|
||||
})
|
||||
.then(
|
||||
@@ -544,11 +548,11 @@ export function maybeRunQueryTrigger(
|
||||
};
|
||||
},
|
||||
err => {
|
||||
if (typeof err === 'string') {
|
||||
throw new Parse.Error(1, err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
const error = resolveError(err, {
|
||||
code: Parse.Error.SCRIPT_FAILED,
|
||||
message: 'Script failed. Unknown error.',
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -583,6 +587,9 @@ export function maybeRunValidator(request, functionName) {
|
||||
if (!theValidator) {
|
||||
return;
|
||||
}
|
||||
if (typeof theValidator === 'object' && theValidator.skipWithMasterKey && request.master) {
|
||||
request.skipWithMasterKey = true;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
@@ -797,6 +804,9 @@ export function maybeRunTrigger(
|
||||
return maybeRunValidator(request, `${triggerType}.${parseObject.className}`);
|
||||
})
|
||||
.then(() => {
|
||||
if (request.skipWithMasterKey) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const promise = trigger(request);
|
||||
if (
|
||||
triggerType === Types.afterSave ||
|
||||
@@ -873,6 +883,9 @@ export async function maybeRunFileTrigger(triggerType, fileObject, config, auth)
|
||||
try {
|
||||
const request = getRequestFileObject(triggerType, auth, fileObject, config);
|
||||
await maybeRunValidator(request, `${triggerType}.${FileClassName}`);
|
||||
if (request.skipWithMasterKey) {
|
||||
return fileObject;
|
||||
}
|
||||
const result = await fileTrigger(request);
|
||||
logTriggerSuccessBeforeHook(
|
||||
triggerType,
|
||||
@@ -903,6 +916,9 @@ export async function maybeRunConnectTrigger(triggerType, request) {
|
||||
}
|
||||
request.user = await userForSessionToken(request.sessionToken);
|
||||
await maybeRunValidator(request, `${triggerType}.${ConnectClassName}`);
|
||||
if (request.skipWithMasterKey) {
|
||||
return;
|
||||
}
|
||||
return trigger(request);
|
||||
}
|
||||
|
||||
@@ -916,6 +932,9 @@ export async function maybeRunSubscribeTrigger(triggerType, className, request)
|
||||
request.query = parseQuery;
|
||||
request.user = await userForSessionToken(request.sessionToken);
|
||||
await maybeRunValidator(request, `${triggerType}.${className}`);
|
||||
if (request.skipWithMasterKey) {
|
||||
return;
|
||||
}
|
||||
await trigger(request);
|
||||
const query = request.query.toJSON();
|
||||
if (query.keys) {
|
||||
@@ -937,6 +956,9 @@ export async function maybeRunAfterEventTrigger(triggerType, className, request)
|
||||
}
|
||||
request.user = await userForSessionToken(request.sessionToken);
|
||||
await maybeRunValidator(request, `${triggerType}.${className}`);
|
||||
if (request.skipWithMasterKey) {
|
||||
return;
|
||||
}
|
||||
return trigger(request);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user