First part of schemas PUT

This commit is contained in:
Drew Gross
2016-02-09 11:26:46 -08:00
parent 6db40f0bf4
commit cef5a5fabf
2 changed files with 148 additions and 20 deletions

View File

@@ -94,7 +94,7 @@ describe('schemas', () => {
headers: restKeyHeaders,
}, (error, response, body) => {
expect(response.statusCode).toEqual(401);
expect(body.error).toEqual('unauthorized');
expect(body.error).toEqual('master key not specified');
done();
});
});
@@ -318,4 +318,101 @@ describe('schemas', () => {
done();
});
});
it('requires the master key to modify schemas', done => {
request.post({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders,
json: true,
body: {},
}, (error, response, body) => {
request.put({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: noAuthHeaders,
json: true,
body: {},
}, (error, response, body) => {
expect(response.statusCode).toEqual(403);
expect(body.error).toEqual('unauthorized');
done();
});
});
});
it('rejects class name mis-matches', done => {
request.put({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders,
json: true,
body: {className: 'WrongClassName'}
}, (error, response, body) => {
expect(response.statusCode).toEqual(400);
expect(body.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
expect(body.error).toEqual('class name mismatch between WrongClassName and NewClass');
});
});
it('refuses to add fields to non-existent classes', done => {
request.put({
url: 'http://localhost:8378/1/schemas/NoClass',
headers: masterKeyHeaders,
json: true,
body: {
fields: {
newField: {type: 'String'}
}
}
}, (error, response, body) => {
expect(response.statusCode).toEqual(400);
expect(body.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
expect(body.error).toEqual('class NoClass does not exist');
done();
});
});
it('put with no modifications returns all fields', done => {
var obj = hasAllPODobject();
obj.save()
.then(() => {
request.put({
url: 'http://localhost:8378/1/schemas/HasAllPOD'
headers: masterKeyHeaders,
json: true,
body: {},
}, (error, response, body) => {
expect(body).toEqual(plainOldDataSchema);
done();
});
});
});
it('lets you add fields', done => {
request.post({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders,
json: true,
body: {},
}, (error, response, body) => {
request.put({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders,
json: true,
body: {
fields: {
newField: {type: 'String'}
}
}
}, (error, response, body) => {
expect(body).toEqual('blah');
request.get({
url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders,
json: true,
}, (error, response, body) => {
expect(body).toEqual('blah');
done();
});
});
})
});
});

View File

@@ -7,6 +7,23 @@ var express = require('express'),
var router = new PromiseRouter();
function masterKeyRequiredResponse() {
return Promise.resolve({
status: 401,
response: {error: 'master key not specified'},
})
}
function classNameMismatchResponse(bodyClass, pathClass) {
return Promise.resolve({
status: 400,
response: {
code: Parse.Error.INVALID_CLASS_NAME,
error: 'class name mismatch between ' + bodyClass + ' and ' + pathClass,
}
});
}
function mongoFieldTypeToSchemaAPIType(type) {
if (type[0] === '*') {
return {
@@ -55,10 +72,7 @@ function mongoSchemaToSchemaAPIResponse(schema) {
function getAllSchemas(req) {
if (!req.auth.isMaster) {
return Promise.resolve({
status: 401,
response: {error: 'master key not specified'},
});
return masterKeyRequiredResponse();
}
return req.config.database.collection('_SCHEMA')
.then(coll => coll.find({}).toArray())
@@ -69,10 +83,7 @@ function getAllSchemas(req) {
function getOneSchema(req) {
if (!req.auth.isMaster) {
return Promise.resolve({
status: 401,
response: {error: 'unauthorized'},
});
return masterKeyRequiredResponse();
}
return req.config.database.collection('_SCHEMA')
.then(coll => coll.findOne({'_id': req.params.className}))
@@ -88,20 +99,11 @@ function getOneSchema(req) {
function createSchema(req) {
if (!req.auth.isMaster) {
return Promise.resolve({
status: 401,
response: {error: 'master key not specified'},
});
return masterKeyRequiredResponse();
}
if (req.params.className && req.body.className) {
if (req.params.className != req.body.className) {
return Promise.resolve({
status: 400,
response: {
code: Parse.Error.INVALID_CLASS_NAME,
error: 'class name mismatch between ' + req.body.className + ' and ' + req.params.className,
},
});
return classNameMismatchResponse(req.body.className, req.params.className);
}
}
var className = req.params.className || req.body.className;
@@ -123,9 +125,38 @@ function createSchema(req) {
}));
}
function modifySchema(req) {
if (!req.auth.isMaster) {
return masterKeyRequiredResponse();
}
if (req.body.className && req.body.className != req.params.className) {
return classNameMismatchResponse(req.body.className, req.path.className);
}
if (!req.body.fields) {
req.body.fields = {};
}
return req.config.database.loadSchema()
.then(schema => schema.hasClass(req.params.className))
.then(hasClass => {
if (!hasClass) {
return Promise.resolve({
status: 400,
response: {
code: Parse.Error.INVALID_CLASS_NAME,
error: 'class ' + req.params.className + ' does not exist',
}
});
}
});
}
router.route('GET', '/schemas', getAllSchemas);
router.route('GET', '/schemas/:className', getOneSchema);
router.route('POST', '/schemas', createSchema);
router.route('POST', '/schemas/:className', createSchema);
router.route('PUT', '/schemas/:className', modifySchema);
module.exports = router;