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();
|
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) {
|
it('basic beforeSave requireUserKey on User Class', async function (done) {
|
||||||
Parse.Cloud.beforeSave(Parse.User, () => {}, {
|
Parse.Cloud.beforeSave(Parse.User, () => {}, {
|
||||||
requireUser: true,
|
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) {
|
it('beforeSave rejection with custom error code', function (done) {
|
||||||
Parse.Cloud.beforeSave('BeforeSaveFailWithErrorCode', function () {
|
Parse.Cloud.beforeSave('BeforeSaveFailWithErrorCode', function () {
|
||||||
throw new Parse.Error(999, 'Nope');
|
throw new Parse.Error(999, 'Nope');
|
||||||
@@ -1894,7 +1912,7 @@ describe('beforeFind hooks', () => {
|
|||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
expect(err.code).toBe(1);
|
expect(err.code).toBe(141);
|
||||||
expect(err.message).toEqual('Do not run that query');
|
expect(err.message).toEqual('Do not run that query');
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -712,6 +712,7 @@ module.exports = ParseCloud;
|
|||||||
* @property {Boolean} requireUser whether the cloud trigger requires a user.
|
* @property {Boolean} requireUser whether the cloud trigger requires a user.
|
||||||
* @property {Boolean} requireMaster whether the cloud trigger requires a master key.
|
* @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} 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 {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
|
* @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);
|
return resolve(response);
|
||||||
},
|
},
|
||||||
error: function (error) {
|
error: function (error) {
|
||||||
if (error instanceof Parse.Error) {
|
const e = resolveError(error, {
|
||||||
reject(error);
|
code: Parse.Error.SCRIPT_FAILED,
|
||||||
} else if (error instanceof Error) {
|
message: 'Script failed. Unknown error.',
|
||||||
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error.message));
|
});
|
||||||
} else {
|
reject(e);
|
||||||
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -420,6 +418,9 @@ export function maybeRunAfterFindTrigger(triggerType, auth, className, objects,
|
|||||||
return maybeRunValidator(request, `${triggerType}.${className}`);
|
return maybeRunValidator(request, `${triggerType}.${className}`);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return request.objects;
|
||||||
|
}
|
||||||
const response = trigger(request);
|
const response = trigger(request);
|
||||||
if (response && typeof response.then === 'function') {
|
if (response && typeof response.then === 'function') {
|
||||||
return response.then(results => {
|
return response.then(results => {
|
||||||
@@ -482,6 +483,9 @@ export function maybeRunQueryTrigger(
|
|||||||
return maybeRunValidator(requestObject, `${triggerType}.${className}`);
|
return maybeRunValidator(requestObject, `${triggerType}.${className}`);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
if (requestObject.skipWithMasterKey) {
|
||||||
|
return requestObject.query;
|
||||||
|
}
|
||||||
return trigger(requestObject);
|
return trigger(requestObject);
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
@@ -544,11 +548,11 @@ export function maybeRunQueryTrigger(
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
if (typeof err === 'string') {
|
const error = resolveError(err, {
|
||||||
throw new Parse.Error(1, err);
|
code: Parse.Error.SCRIPT_FAILED,
|
||||||
} else {
|
message: 'Script failed. Unknown error.',
|
||||||
throw err;
|
});
|
||||||
}
|
throw error;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -583,6 +587,9 @@ export function maybeRunValidator(request, functionName) {
|
|||||||
if (!theValidator) {
|
if (!theValidator) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (typeof theValidator === 'object' && theValidator.skipWithMasterKey && request.master) {
|
||||||
|
request.skipWithMasterKey = true;
|
||||||
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -797,6 +804,9 @@ export function maybeRunTrigger(
|
|||||||
return maybeRunValidator(request, `${triggerType}.${parseObject.className}`);
|
return maybeRunValidator(request, `${triggerType}.${parseObject.className}`);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
const promise = trigger(request);
|
const promise = trigger(request);
|
||||||
if (
|
if (
|
||||||
triggerType === Types.afterSave ||
|
triggerType === Types.afterSave ||
|
||||||
@@ -873,6 +883,9 @@ export async function maybeRunFileTrigger(triggerType, fileObject, config, auth)
|
|||||||
try {
|
try {
|
||||||
const request = getRequestFileObject(triggerType, auth, fileObject, config);
|
const request = getRequestFileObject(triggerType, auth, fileObject, config);
|
||||||
await maybeRunValidator(request, `${triggerType}.${FileClassName}`);
|
await maybeRunValidator(request, `${triggerType}.${FileClassName}`);
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return fileObject;
|
||||||
|
}
|
||||||
const result = await fileTrigger(request);
|
const result = await fileTrigger(request);
|
||||||
logTriggerSuccessBeforeHook(
|
logTriggerSuccessBeforeHook(
|
||||||
triggerType,
|
triggerType,
|
||||||
@@ -903,6 +916,9 @@ export async function maybeRunConnectTrigger(triggerType, request) {
|
|||||||
}
|
}
|
||||||
request.user = await userForSessionToken(request.sessionToken);
|
request.user = await userForSessionToken(request.sessionToken);
|
||||||
await maybeRunValidator(request, `${triggerType}.${ConnectClassName}`);
|
await maybeRunValidator(request, `${triggerType}.${ConnectClassName}`);
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return trigger(request);
|
return trigger(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,6 +932,9 @@ export async function maybeRunSubscribeTrigger(triggerType, className, request)
|
|||||||
request.query = parseQuery;
|
request.query = parseQuery;
|
||||||
request.user = await userForSessionToken(request.sessionToken);
|
request.user = await userForSessionToken(request.sessionToken);
|
||||||
await maybeRunValidator(request, `${triggerType}.${className}`);
|
await maybeRunValidator(request, `${triggerType}.${className}`);
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await trigger(request);
|
await trigger(request);
|
||||||
const query = request.query.toJSON();
|
const query = request.query.toJSON();
|
||||||
if (query.keys) {
|
if (query.keys) {
|
||||||
@@ -937,6 +956,9 @@ export async function maybeRunAfterEventTrigger(triggerType, className, request)
|
|||||||
}
|
}
|
||||||
request.user = await userForSessionToken(request.sessionToken);
|
request.user = await userForSessionToken(request.sessionToken);
|
||||||
await maybeRunValidator(request, `${triggerType}.${className}`);
|
await maybeRunValidator(request, `${triggerType}.${className}`);
|
||||||
|
if (request.skipWithMasterKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return trigger(request);
|
return trigger(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user