Skip to content

Commit

Permalink
Validation Handler Update (#6968)
Browse files Browse the repository at this point in the history
* Initial Commit

* Update FunctionsRouter.js

* Update FunctionsRouter.js

* Change params to fields

* Changes requested

* Fix failing tests

* More tests

* More tests

* Remove existing functionality

* Remove legacy tests

* fix array typo

* Update triggers.js

* Docs

* Allow requireUserKeys to be object

* validateMasterKey

* Improve documentation

Co-authored-by: Diamond Lewis <findlewis@gmail.com>
  • Loading branch information
dblythy and dplewis authored Oct 25, 2020
1 parent e89cf25 commit c2f2281
Show file tree
Hide file tree
Showing 8 changed files with 1,752 additions and 176 deletions.
1,174 changes: 1,174 additions & 0 deletions spec/CloudCode.Validator.spec.js

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions spec/CloudCode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ describe('Cloud Code', () => {
);
});

it('returns an empty error', done => {
Parse.Cloud.define('cloudCodeWithError', () => {
throw null;
});

Parse.Cloud.run('cloudCodeWithError').then(
() => done.fail('should not succeed'),
e => {
expect(e.code).toEqual(141);
expect(e.message).toEqual('Script failed.');
done();
}
);
});

it('beforeSave rejection with custom error code', function (done) {
Parse.Cloud.beforeSave('BeforeSaveFailWithErrorCode', function () {
throw new Parse.Error(999, 'Nope');
Expand Down Expand Up @@ -2675,6 +2690,34 @@ describe('beforeLogin hook', () => {
expect(result).toBe(file);
});

it('throw custom error from beforeSaveFile', async done => {
Parse.Cloud.beforeSaveFile(() => {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'It should fail');
});
try {
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
await file.save({ useMasterKey: true });
fail('error should have thrown');
} catch (e) {
expect(e.code).toBe(Parse.Error.SCRIPT_FAILED);
done();
}
});

it('throw empty error from beforeSaveFile', async done => {
Parse.Cloud.beforeSaveFile(() => {
throw null;
});
try {
const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain');
await file.save({ useMasterKey: true });
fail('error should have thrown');
} catch (e) {
expect(e.code).toBe(130);
done();
}
});

it('beforeSaveFile should return file that is already saved and not save anything to files adapter', async () => {
await reconfigureServer({ filesAdapter: mockAdapter });
const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough();
Expand Down
118 changes: 44 additions & 74 deletions spec/ParseAPI.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const headers = {
};

describe_only_db('mongo')('miscellaneous', () => {
it('test rest_create_app', function(done) {
it('test rest_create_app', function (done) {
let appId;
Parse._request('POST', 'rest_create_app')
.then(res => {
Expand Down Expand Up @@ -57,19 +57,19 @@ describe_only_db('mongo')('miscellaneous', () => {
});
});

describe('miscellaneous', function() {
it('create a GameScore object', function(done) {
describe('miscellaneous', function () {
it('create a GameScore object', function (done) {
const obj = new Parse.Object('GameScore');
obj.set('score', 1337);
obj.save().then(function(obj) {
obj.save().then(function (obj) {
expect(typeof obj.id).toBe('string');
expect(typeof obj.createdAt.toGMTString()).toBe('string');
done();
}, done.fail);
});

it('get a TestObject', function(done) {
create({ bloop: 'blarg' }, async function(obj) {
it('get a TestObject', function (done) {
create({ bloop: 'blarg' }, async function (obj) {
const t2 = new TestObject({ objectId: obj.id });
const obj2 = await t2.fetch();
expect(obj2.get('bloop')).toEqual('blarg');
Expand All @@ -79,8 +79,8 @@ describe('miscellaneous', function() {
});
});

it('create a valid parse user', function(done) {
createTestUser().then(function(data) {
it('create a valid parse user', function (done) {
createTestUser().then(function (data) {
expect(data.id).not.toBeUndefined();
expect(data.getSessionToken()).not.toBeUndefined();
expect(data.get('password')).toBeUndefined();
Expand Down Expand Up @@ -297,8 +297,8 @@ describe('miscellaneous', function() {
});
});

it('succeed in logging in', function(done) {
createTestUser().then(async function(u) {
it('succeed in logging in', function (done) {
createTestUser().then(async function (u) {
expect(typeof u.id).toEqual('string');

const user = await Parse.User.logIn('test', 'moon-y');
Expand All @@ -310,7 +310,7 @@ describe('miscellaneous', function() {
}, fail);
});

it('increment with a user object', function(done) {
it('increment with a user object', function (done) {
createTestUser()
.then(user => {
user.increment('foo');
Expand Down Expand Up @@ -338,7 +338,7 @@ describe('miscellaneous', function() {
);
});

it('save various data types', function(done) {
it('save various data types', function (done) {
const obj = new TestObject();
obj.set('date', new Date());
obj.set('array', [1, 2, 3]);
Expand All @@ -358,7 +358,7 @@ describe('miscellaneous', function() {
});
});

it('query with limit', function(done) {
it('query with limit', function (done) {
const baz = new TestObject({ foo: 'baz' });
const qux = new TestObject({ foo: 'qux' });
baz
Expand All @@ -383,7 +383,7 @@ describe('miscellaneous', function() {
);
});

it('query without limit get default 100 records', function(done) {
it('query without limit get default 100 records', function (done) {
const objects = [];
for (let i = 0; i < 150; i++) {
objects.push(new TestObject({ name: 'name' + i }));
Expand All @@ -404,7 +404,7 @@ describe('miscellaneous', function() {
);
});

it('basic saveAll', function(done) {
it('basic saveAll', function (done) {
const alpha = new TestObject({ letter: 'alpha' });
const beta = new TestObject({ letter: 'beta' });
Parse.Object.saveAll([alpha, beta])
Expand All @@ -425,26 +425,26 @@ describe('miscellaneous', function() {
);
});

it('test beforeSave set object acl success', function(done) {
it('test beforeSave set object acl success', function (done) {
const acl = new Parse.ACL({
'*': { read: true, write: false },
});
Parse.Cloud.beforeSave('BeforeSaveAddACL', function(req) {
Parse.Cloud.beforeSave('BeforeSaveAddACL', function (req) {
req.object.setACL(acl);
});

const obj = new Parse.Object('BeforeSaveAddACL');
obj.set('lol', true);
obj.save().then(
function() {
function () {
const query = new Parse.Query('BeforeSaveAddACL');
query.get(obj.id).then(
function(objAgain) {
function (objAgain) {
expect(objAgain.get('lol')).toBeTruthy();
expect(objAgain.getACL().equals(acl));
done();
},
function(error) {
function (error) {
fail(error);
done();
}
Expand Down Expand Up @@ -667,10 +667,10 @@ describe('miscellaneous', function() {
});
});

it('test afterSave get full object on create and update', function(done) {
it('test afterSave get full object on create and update', function (done) {
let triggerTime = 0;
// Register a mock beforeSave hook
Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
const object = req.object;
expect(object instanceof Parse.Object).toBeTruthy();
expect(object.id).not.toBeUndefined();
Expand All @@ -694,29 +694,29 @@ describe('miscellaneous', function() {
obj.set('fooAgain', 'barAgain');
obj
.save()
.then(function() {
.then(function () {
// We only update foo
obj.set('foo', 'baz');
return obj.save();
})
.then(
function() {
function () {
// Make sure the checking has been triggered
expect(triggerTime).toBe(2);
done();
},
function(error) {
function (error) {
fail(error);
done();
}
);
});

it('test afterSave get original object on update', function(done) {
it('test afterSave get original object on update', function (done) {
let triggerTime = 0;
// Register a mock beforeSave hook

Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
const object = req.object;
expect(object instanceof Parse.Object).toBeTruthy();
expect(object.get('fooAgain')).toEqual('barAgain');
Expand Down Expand Up @@ -750,18 +750,18 @@ describe('miscellaneous', function() {
obj.set('fooAgain', 'barAgain');
obj
.save()
.then(function() {
.then(function () {
// We only update foo
obj.set('foo', 'baz');
return obj.save();
})
.then(
function() {
function () {
// Make sure the checking has been triggered
expect(triggerTime).toBe(2);
done();
},
function(error) {
function (error) {
jfail(error);
done();
}
Expand All @@ -771,7 +771,7 @@ describe('miscellaneous', function() {
it('test afterSave get full original object even req auth can not query it', done => {
let triggerTime = 0;
// Register a mock beforeSave hook
Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
const object = req.object;
const originalObject = req.original;
if (triggerTime == 0) {
Expand Down Expand Up @@ -802,18 +802,18 @@ describe('miscellaneous', function() {
obj.setACL(acl);
obj
.save()
.then(function() {
.then(function () {
// We only update foo
obj.set('foo', 'baz');
return obj.save();
})
.then(
function() {
function () {
// Make sure the checking has been triggered
expect(triggerTime).toBe(2);
done();
},
function(error) {
function (error) {
jfail(error);
done();
}
Expand All @@ -823,7 +823,7 @@ describe('miscellaneous', function() {
it('afterSave flattens custom operations', done => {
let triggerTime = 0;
// Register a mock beforeSave hook
Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
const object = req.object;
expect(object instanceof Parse.Object).toBeTruthy();
const originalObject = req.original;
Expand Down Expand Up @@ -865,7 +865,7 @@ describe('miscellaneous', function() {
it('beforeSave receives ACL', done => {
let triggerTime = 0;
// Register a mock beforeSave hook
Parse.Cloud.beforeSave('GameScore', function(req) {
Parse.Cloud.beforeSave('GameScore', function (req) {
const object = req.object;
if (triggerTime == 0) {
const acl = object.getACL();
Expand Down Expand Up @@ -909,7 +909,7 @@ describe('miscellaneous', function() {
it('afterSave receives ACL', done => {
let triggerTime = 0;
// Register a mock beforeSave hook
Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
const object = req.object;
if (triggerTime == 0) {
const acl = object.getACL();
Expand Down Expand Up @@ -1057,14 +1057,14 @@ describe('miscellaneous', function() {
);
});

it('test beforeSave/afterSave get installationId', function(done) {
it('test beforeSave/afterSave get installationId', function (done) {
let triggerTime = 0;
Parse.Cloud.beforeSave('GameScore', function(req) {
Parse.Cloud.beforeSave('GameScore', function (req) {
triggerTime++;
expect(triggerTime).toEqual(1);
expect(req.installationId).toEqual('yolo');
});
Parse.Cloud.afterSave('GameScore', function(req) {
Parse.Cloud.afterSave('GameScore', function (req) {
triggerTime++;
expect(triggerTime).toEqual(2);
expect(req.installationId).toEqual('yolo');
Expand All @@ -1087,14 +1087,14 @@ describe('miscellaneous', function() {
});
});

it('test beforeDelete/afterDelete get installationId', function(done) {
it('test beforeDelete/afterDelete get installationId', function (done) {
let triggerTime = 0;
Parse.Cloud.beforeDelete('GameScore', function(req) {
Parse.Cloud.beforeDelete('GameScore', function (req) {
triggerTime++;
expect(triggerTime).toEqual(1);
expect(req.installationId).toEqual('yolo');
});
Parse.Cloud.afterDelete('GameScore', function(req) {
Parse.Cloud.afterDelete('GameScore', function (req) {
triggerTime++;
expect(triggerTime).toEqual(2);
expect(req.installationId).toEqual('yolo');
Expand Down Expand Up @@ -1170,33 +1170,6 @@ describe('miscellaneous', function() {
});
});

it('test cloud function parameter validation', done => {
// Register a function with validation
Parse.Cloud.define(
'functionWithParameterValidationFailure',
() => {
return 'noway';
},
request => {
return request.params.success === 100;
}
);

Parse.Cloud.run('functionWithParameterValidationFailure', {
success: 500,
}).then(
() => {
fail('Validation should not have succeeded');
done();
},
e => {
expect(e.code).toEqual(142);
expect(e.message).toEqual('Validation failed.');
done();
}
);
});

it('can handle null params in cloud functions (regression test for #1742)', done => {
Parse.Cloud.define('func', request => {
expect(request.params.nullParam).toEqual(null);
Expand Down Expand Up @@ -1715,10 +1688,7 @@ describe('miscellaneous', function() {

it('purge empty class', done => {
const testSchema = new Parse.Schema('UnknownClass');
testSchema
.purge()
.then(done)
.catch(done.fail);
testSchema.purge().then(done).catch(done.fail);
});

it('should not update schema beforeSave #2672', done => {
Expand Down
Loading

0 comments on commit c2f2281

Please sign in to comment.