Accept context via header X-Parse-Cloud-Context (#7437)
* failing testcase * add header * switch to X-Parse-Cloud-Context header * add back blank line that lint removed * test replacing context header with body context. Add support for setting body with json string * add back blank line * cover error when _context body is wrong * Update middlewares.js * revert accidental status change * make sure context always decodes to an object else throw error * improve context object check Co-authored-by: Antonio Davi Macedo Coelho de Castro <adavimacedo@gmail.com>
This commit is contained in:
@@ -2519,6 +2519,201 @@ describe('afterFind hooks', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error if context header is malformed', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', () => {
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', () => {
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': 'key',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
},
|
||||
});
|
||||
try {
|
||||
await req;
|
||||
fail('Should have thrown error');
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
expect(e.data.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
}
|
||||
expect(calledBefore).toBe(false);
|
||||
expect(calledAfter).toBe(false);
|
||||
});
|
||||
|
||||
it('should throw error if context header is string "1"', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', () => {
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', () => {
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': '1',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
},
|
||||
});
|
||||
try {
|
||||
await req;
|
||||
fail('Should have thrown error');
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
expect(e.data.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
}
|
||||
expect(calledBefore).toBe(false);
|
||||
expect(calledAfter).toBe(false);
|
||||
});
|
||||
|
||||
it('should expose context in beforeSave/afterSave via header', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', req => {
|
||||
expect(req.object.get('foo')).toEqual('bar');
|
||||
expect(req.context.otherKey).toBe(1);
|
||||
expect(req.context.key).toBe('value');
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', req => {
|
||||
expect(req.object.get('foo')).toEqual('bar');
|
||||
expect(req.context.otherKey).toBe(1);
|
||||
expect(req.context.key).toBe('value');
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': '{"key":"value","otherKey":1}',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
},
|
||||
});
|
||||
await req;
|
||||
expect(calledBefore).toBe(true);
|
||||
expect(calledAfter).toBe(true);
|
||||
});
|
||||
|
||||
it('should override header context with body context in beforeSave/afterSave', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', req => {
|
||||
expect(req.object.get('foo')).toEqual('bar');
|
||||
expect(req.context.otherKey).toBe(10);
|
||||
expect(req.context.key).toBe('hello');
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', req => {
|
||||
expect(req.object.get('foo')).toEqual('bar');
|
||||
expect(req.context.otherKey).toBe(10);
|
||||
expect(req.context.key).toBe('hello');
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': '{"key":"value","otherKey":1}',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
_ApplicationId: 'test',
|
||||
_context: '{"key":"hello","otherKey":10}',
|
||||
},
|
||||
});
|
||||
await req;
|
||||
expect(calledBefore).toBe(true);
|
||||
expect(calledAfter).toBe(true);
|
||||
});
|
||||
|
||||
it('should throw error if context body is malformed', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', () => {
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', () => {
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': '{"key":"value","otherKey":1}',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
_ApplicationId: 'test',
|
||||
_context: 'key',
|
||||
},
|
||||
});
|
||||
try {
|
||||
await req;
|
||||
fail('Should have thrown error');
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
expect(e.data.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
}
|
||||
expect(calledBefore).toBe(false);
|
||||
expect(calledAfter).toBe(false);
|
||||
});
|
||||
|
||||
it('should throw error if context body is string "true"', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
Parse.Cloud.beforeSave('TestObject', () => {
|
||||
calledBefore = true;
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', () => {
|
||||
calledAfter = true;
|
||||
});
|
||||
const req = request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
headers: {
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Cloud-Context': '{"key":"value","otherKey":1}',
|
||||
},
|
||||
body: {
|
||||
foo: 'bar',
|
||||
_ApplicationId: 'test',
|
||||
_context: 'true',
|
||||
},
|
||||
});
|
||||
try {
|
||||
await req;
|
||||
fail('Should have thrown error');
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
expect(e.data.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
}
|
||||
expect(calledBefore).toBe(false);
|
||||
expect(calledAfter).toBe(false);
|
||||
});
|
||||
|
||||
it('should expose context in before and afterSave', async () => {
|
||||
let calledBefore = false;
|
||||
let calledAfter = false;
|
||||
@@ -2804,6 +2999,26 @@ describe('afterLogin hook', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('context options should override _context object property when saving a new object', async () => {
|
||||
Parse.Cloud.beforeSave('TestObject', req => {
|
||||
expect(req.context.a).toEqual('a');
|
||||
expect(req.context.hello).not.toBeDefined();
|
||||
expect(req._context).not.toBeDefined();
|
||||
expect(req.object._context).not.toBeDefined();
|
||||
expect(req.object.context).not.toBeDefined();
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject', req => {
|
||||
expect(req.context.a).toEqual('a');
|
||||
expect(req.context.hello).not.toBeDefined();
|
||||
expect(req._context).not.toBeDefined();
|
||||
expect(req.object._context).not.toBeDefined();
|
||||
expect(req.object.context).not.toBeDefined();
|
||||
});
|
||||
const obj = new TestObject();
|
||||
obj.set('_context', { hello: 'world' });
|
||||
await obj.save(null, { context: { a: 'a' } });
|
||||
});
|
||||
|
||||
it('should have access to context when saving a new object', async () => {
|
||||
Parse.Cloud.beforeSave('TestObject', req => {
|
||||
expect(req.context.a).toEqual('a');
|
||||
|
||||
Reference in New Issue
Block a user