Skip to content

Commit 6fc3afc

Browse files
authored
skipWithMasterKey on Built-In Validator (#6972)
* Initial Commit * Change to resolveMasterKey * Change to skipWithMasterKey
1 parent 7f3ea3f commit 6fc3afc

File tree

4 files changed

+179
-13
lines changed

4 files changed

+179
-13
lines changed

spec/CloudCode.Validator.spec.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,131 @@ describe('cloud validator', () => {
554554
done();
555555
});
556556

557+
it('basic beforeSave skipWithMasterKey', async function (done) {
558+
Parse.Cloud.beforeSave(
559+
'BeforeSave',
560+
() => {
561+
throw 'before save should have resolved using masterKey.';
562+
},
563+
{
564+
skipWithMasterKey: true,
565+
}
566+
);
567+
const obj = new Parse.Object('BeforeSave');
568+
obj.set('foo', 'bar');
569+
await obj.save(null, { useMasterKey: true });
570+
expect(obj.get('foo')).toBe('bar');
571+
done();
572+
});
573+
574+
it('basic beforeFind skipWithMasterKey', async function (done) {
575+
Parse.Cloud.beforeFind(
576+
'beforeFind',
577+
() => {
578+
throw 'before find should have resolved using masterKey.';
579+
},
580+
{
581+
skipWithMasterKey: true,
582+
}
583+
);
584+
const obj = new Parse.Object('beforeFind');
585+
obj.set('foo', 'bar');
586+
await obj.save();
587+
expect(obj.get('foo')).toBe('bar');
588+
589+
const query = new Parse.Query('beforeFind');
590+
try {
591+
const first = await query.first({ useMasterKey: true });
592+
expect(first).toBeDefined();
593+
expect(first.id).toBe(obj.id);
594+
done();
595+
} catch (e) {
596+
console.log(e);
597+
console.log(e.code);
598+
throw e;
599+
}
600+
});
601+
602+
it('basic beforeDelete skipWithMasterKey', async function (done) {
603+
Parse.Cloud.beforeDelete(
604+
'beforeFind',
605+
() => {
606+
throw 'before find should have resolved using masterKey.';
607+
},
608+
{
609+
skipWithMasterKey: true,
610+
}
611+
);
612+
const obj = new Parse.Object('beforeFind');
613+
obj.set('foo', 'bar');
614+
await obj.save();
615+
expect(obj.get('foo')).toBe('bar');
616+
await obj.destroy({ useMasterKey: true });
617+
done();
618+
});
619+
620+
it('basic beforeSaveFile skipWithMasterKey', async done => {
621+
Parse.Cloud.beforeSaveFile(
622+
() => {
623+
throw 'beforeSaveFile should have resolved using master key.';
624+
},
625+
{
626+
skipWithMasterKey: true,
627+
}
628+
);
629+
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
630+
const result = await file.save({ useMasterKey: true });
631+
expect(result).toBe(file);
632+
done();
633+
});
634+
635+
it('beforeSave validateMasterKey and skipWithMasterKey fail', async function (done) {
636+
Parse.Cloud.beforeSave(
637+
'BeforeSave',
638+
() => {
639+
throw 'beforeSaveFile should have resolved using master key.';
640+
},
641+
{
642+
fields: ['foo'],
643+
validateMasterKey: true,
644+
skipWithMasterKey: true,
645+
}
646+
);
647+
648+
const obj = new Parse.Object('BeforeSave');
649+
try {
650+
await obj.save(null, { useMasterKey: true });
651+
fail('function should have failed.');
652+
} catch (error) {
653+
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
654+
expect(error.message).toEqual('Validation failed. Please specify data for foo.');
655+
done();
656+
}
657+
});
658+
659+
it('beforeSave validateMasterKey and skipWithMasterKey success', async function (done) {
660+
Parse.Cloud.beforeSave(
661+
'BeforeSave',
662+
() => {
663+
throw 'beforeSaveFile should have resolved using master key.';
664+
},
665+
{
666+
fields: ['foo'],
667+
validateMasterKey: true,
668+
skipWithMasterKey: true,
669+
}
670+
);
671+
672+
const obj = new Parse.Object('BeforeSave');
673+
obj.set('foo', 'bar');
674+
try {
675+
await obj.save(null, { useMasterKey: true });
676+
done();
677+
} catch (error) {
678+
fail('error should not have been called.');
679+
}
680+
});
681+
557682
it('basic beforeSave requireUserKey on User Class', async function (done) {
558683
Parse.Cloud.beforeSave(Parse.User, () => {}, {
559684
requireUser: true,

spec/CloudCode.spec.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,24 @@ describe('Cloud Code', () => {
122122
);
123123
});
124124

125+
it('beforeFind can throw string', async function (done) {
126+
Parse.Cloud.beforeFind('beforeFind', () => {
127+
throw 'throw beforeFind';
128+
});
129+
const obj = new Parse.Object('beforeFind');
130+
obj.set('foo', 'bar');
131+
await obj.save();
132+
expect(obj.get('foo')).toBe('bar');
133+
try {
134+
const query = new Parse.Query('beforeFind');
135+
await query.first();
136+
} catch (e) {
137+
expect(e.code).toBe(141);
138+
expect(e.message).toBe('throw beforeFind');
139+
done();
140+
}
141+
});
142+
125143
it('beforeSave rejection with custom error code', function (done) {
126144
Parse.Cloud.beforeSave('BeforeSaveFailWithErrorCode', function () {
127145
throw new Parse.Error(999, 'Nope');
@@ -1894,7 +1912,7 @@ describe('beforeFind hooks', () => {
18941912
done();
18951913
},
18961914
err => {
1897-
expect(err.code).toBe(1);
1915+
expect(err.code).toBe(141);
18981916
expect(err.message).toEqual('Do not run that query');
18991917
done();
19001918
}

src/cloud-code/Parse.Cloud.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ module.exports = ParseCloud;
712712
* @property {Boolean} requireUser whether the cloud trigger requires a user.
713713
* @property {Boolean} requireMaster whether the cloud trigger requires a master key.
714714
* @property {Boolean} validateMasterKey whether the validator should run if masterKey is provided. Defaults to false.
715+
* @property {Boolean} skipWithMasterKey whether the cloud code function should be ignored using a masterKey.
715716
*
716717
* @property {Array<String>|Object} requireUserKeys If set, keys required on request.user to make the request.
717718
* @property {String} requireUserKeys.field If requireUserKeys is an object, name of field to validate on request user

src/triggers.js

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,11 @@ export function getResponseObject(request, resolve, reject) {
331331
return resolve(response);
332332
},
333333
error: function (error) {
334-
if (error instanceof Parse.Error) {
335-
reject(error);
336-
} else if (error instanceof Error) {
337-
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error.message));
338-
} else {
339-
reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error));
340-
}
334+
const e = resolveError(error, {
335+
code: Parse.Error.SCRIPT_FAILED,
336+
message: 'Script failed. Unknown error.',
337+
});
338+
reject(e);
341339
},
342340
};
343341
}
@@ -420,6 +418,9 @@ export function maybeRunAfterFindTrigger(triggerType, auth, className, objects,
420418
return maybeRunValidator(request, `${triggerType}.${className}`);
421419
})
422420
.then(() => {
421+
if (request.skipWithMasterKey) {
422+
return request.objects;
423+
}
423424
const response = trigger(request);
424425
if (response && typeof response.then === 'function') {
425426
return response.then(results => {
@@ -482,6 +483,9 @@ export function maybeRunQueryTrigger(
482483
return maybeRunValidator(requestObject, `${triggerType}.${className}`);
483484
})
484485
.then(() => {
486+
if (requestObject.skipWithMasterKey) {
487+
return requestObject.query;
488+
}
485489
return trigger(requestObject);
486490
})
487491
.then(
@@ -544,11 +548,11 @@ export function maybeRunQueryTrigger(
544548
};
545549
},
546550
err => {
547-
if (typeof err === 'string') {
548-
throw new Parse.Error(1, err);
549-
} else {
550-
throw err;
551-
}
551+
const error = resolveError(err, {
552+
code: Parse.Error.SCRIPT_FAILED,
553+
message: 'Script failed. Unknown error.',
554+
});
555+
throw error;
552556
}
553557
);
554558
}
@@ -583,6 +587,9 @@ export function maybeRunValidator(request, functionName) {
583587
if (!theValidator) {
584588
return;
585589
}
590+
if (typeof theValidator === 'object' && theValidator.skipWithMasterKey && request.master) {
591+
request.skipWithMasterKey = true;
592+
}
586593
return new Promise((resolve, reject) => {
587594
return Promise.resolve()
588595
.then(() => {
@@ -797,6 +804,9 @@ export function maybeRunTrigger(
797804
return maybeRunValidator(request, `${triggerType}.${parseObject.className}`);
798805
})
799806
.then(() => {
807+
if (request.skipWithMasterKey) {
808+
return Promise.resolve();
809+
}
800810
const promise = trigger(request);
801811
if (
802812
triggerType === Types.afterSave ||
@@ -873,6 +883,9 @@ export async function maybeRunFileTrigger(triggerType, fileObject, config, auth)
873883
try {
874884
const request = getRequestFileObject(triggerType, auth, fileObject, config);
875885
await maybeRunValidator(request, `${triggerType}.${FileClassName}`);
886+
if (request.skipWithMasterKey) {
887+
return fileObject;
888+
}
876889
const result = await fileTrigger(request);
877890
logTriggerSuccessBeforeHook(
878891
triggerType,
@@ -903,6 +916,9 @@ export async function maybeRunConnectTrigger(triggerType, request) {
903916
}
904917
request.user = await userForSessionToken(request.sessionToken);
905918
await maybeRunValidator(request, `${triggerType}.${ConnectClassName}`);
919+
if (request.skipWithMasterKey) {
920+
return;
921+
}
906922
return trigger(request);
907923
}
908924

@@ -916,6 +932,9 @@ export async function maybeRunSubscribeTrigger(triggerType, className, request)
916932
request.query = parseQuery;
917933
request.user = await userForSessionToken(request.sessionToken);
918934
await maybeRunValidator(request, `${triggerType}.${className}`);
935+
if (request.skipWithMasterKey) {
936+
return;
937+
}
919938
await trigger(request);
920939
const query = request.query.toJSON();
921940
if (query.keys) {
@@ -937,6 +956,9 @@ export async function maybeRunAfterEventTrigger(triggerType, className, request)
937956
}
938957
request.user = await userForSessionToken(request.sessionToken);
939958
await maybeRunValidator(request, `${triggerType}.${className}`);
959+
if (request.skipWithMasterKey) {
960+
return;
961+
}
940962
return trigger(request);
941963
}
942964

0 commit comments

Comments
 (0)