Skip to content

Commit 0895141

Browse files
committed
Merge pull request #228 from drew-gross/master
Implement GET /schemas/:className
2 parents 488b5f1 + 67ee94d commit 0895141

File tree

2 files changed

+149
-72
lines changed

2 files changed

+149
-72
lines changed

schemas.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ function getAllSchemas(req) {
6464
}}));
6565
}
6666

67+
function getOneSchema(req) {
68+
if (!req.auth.isMaster) {
69+
return Promise.resolve({
70+
status: 401,
71+
response: {error: 'unauthorized'},
72+
});
73+
}
74+
return req.config.database.collection('_SCHEMA')
75+
.then(coll => coll.findOne({'_id': req.params.className}))
76+
.then(schema => ({response: mongoSchemaToSchemaAPIResponse(schema)}))
77+
.catch(() => ({
78+
status: 400,
79+
response: {
80+
code: 103,
81+
error: 'class ' + req.params.className + ' does not exist',
82+
}
83+
}));
84+
}
85+
6786
router.route('GET', '/schemas', getAllSchemas);
87+
router.route('GET', '/schemas/:className', getOneSchema);
6888

6989
module.exports = router;

spec/schemas.spec.js

Lines changed: 129 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,60 @@
11
var request = require('request');
22
var dd = require('deep-diff');
3+
var hasAllPODobject = () => {
4+
var obj = new Parse.Object('HasAllPOD');
5+
obj.set('aNumber', 5);
6+
obj.set('aString', 'string');
7+
obj.set('aBool', true);
8+
obj.set('aDate', new Date());
9+
obj.set('aObject', {k1: 'value', k2: true, k3: 5});
10+
obj.set('aArray', ['contents', true, 5]);
11+
obj.set('aGeoPoint', new Parse.GeoPoint({latitude: 0, longitude: 0}));
12+
obj.set('aFile', new Parse.File('f.txt', { base64: 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' }));
13+
var objACL = new Parse.ACL();
14+
objACL.setPublicWriteAccess(false);
15+
obj.setACL(objACL);
16+
return obj;
17+
}
18+
19+
var expectedResponseForHasAllPOD = {
20+
className: 'HasAllPOD',
21+
fields: {
22+
//Default fields
23+
ACL: {type: 'ACL'},
24+
createdAt: {type: 'Date'},
25+
updatedAt: {type: 'Date'},
26+
objectId: {type: 'String'},
27+
//Custom fields
28+
aNumber: {type: 'Number'},
29+
aString: {type: 'String'},
30+
aBool: {type: 'Boolean'},
31+
aDate: {type: 'Date'},
32+
aObject: {type: 'Object'},
33+
aArray: {type: 'Array'},
34+
aGeoPoint: {type: 'GeoPoint'},
35+
aFile: {type: 'File'}
36+
},
37+
};
38+
39+
var expectedResponseforHasPointersAndRelations = {
40+
className: 'HasPointersAndRelations',
41+
fields: {
42+
//Default fields
43+
ACL: {type: 'ACL'},
44+
createdAt: {type: 'Date'},
45+
updatedAt: {type: 'Date'},
46+
objectId: {type: 'String'},
47+
//Custom fields
48+
aPointer: {
49+
type: 'Pointer',
50+
targetClass: 'HasAllPOD',
51+
},
52+
aRelation: {
53+
type: 'Relation',
54+
targetClass: 'HasAllPOD',
55+
},
56+
},
57+
}
358

459
describe('schemas', () => {
560
it('requires the master key to get all schemas', (done) => {
@@ -17,6 +72,21 @@ describe('schemas', () => {
1772
});
1873
});
1974

75+
it('requires the master key to get one schema', (done) => {
76+
request.get({
77+
url: 'http://localhost:8378/1/schemas/SomeSchema',
78+
json: true,
79+
headers: {
80+
'X-Parse-Application-Id': 'test',
81+
'X-Parse-REST-API-Key': 'rest',
82+
},
83+
}, (error, response, body) => {
84+
expect(response.statusCode).toEqual(401);
85+
expect(body.error).toEqual('unauthorized');
86+
done();
87+
});
88+
});
89+
2090
it('responds with empty list when there are no schemas', done => {
2191
request.get({
2292
url: 'http://localhost:8378/1/schemas',
@@ -32,79 +102,66 @@ describe('schemas', () => {
32102
});
33103

34104
it('responds with a list of schemas after creating objects', done => {
35-
var obj1 = new Parse.Object('HasAllPOD');
36-
obj1.set('aNumber', 5);
37-
obj1.set('aString', 'string');
38-
obj1.set('aBool', true);
39-
obj1.set('aDate', new Date());
40-
obj1.set('aObject', {k1: 'value', k2: true, k3: 5});
41-
obj1.set('aArray', ['contents', true, 5]);
42-
obj1.set('aGeoPoint', new Parse.GeoPoint({latitude: 0, longitude: 0}));
43-
obj1.set('aFile', new Parse.File('f.txt', { base64: 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' }));
44-
var obj1ACL = new Parse.ACL();
45-
obj1ACL.setPublicWriteAccess(false);
46-
obj1.setACL(obj1ACL);
105+
var obj1 = hasAllPODobject();
106+
obj1.save().then(savedObj1 => {
107+
var obj2 = new Parse.Object('HasPointersAndRelations');
108+
obj2.set('aPointer', savedObj1);
109+
var relation = obj2.relation('aRelation');
110+
relation.add(obj1);
111+
return obj2.save();
112+
}).then(() => {
113+
request.get({
114+
url: 'http://localhost:8378/1/schemas',
115+
json: true,
116+
headers: {
117+
'X-Parse-Application-Id': 'test',
118+
'X-Parse-Master-Key': 'test',
119+
},
120+
}, (error, response, body) => {
121+
var expected = {
122+
results: [expectedResponseForHasAllPOD,expectedResponseforHasPointersAndRelations]
123+
};
124+
expect(body).toEqual(expected);
125+
done();
126+
})
127+
});
128+
});
47129

48-
obj1.save().then(savedObj1 => {
49-
var obj2 = new Parse.Object('HasPointersAndRelations');
50-
obj2.set('aPointer', savedObj1);
51-
var relation = obj2.relation('aRelation');
52-
relation.add(obj1);
53-
return obj2.save();
54-
}).then(() => {
55-
request.get({
56-
url: 'http://localhost:8378/1/schemas',
57-
json: true,
58-
headers: {
59-
'X-Parse-Application-Id': 'test',
60-
'X-Parse-Master-Key': 'test',
61-
},
62-
}, (error, response, body) => {
63-
var expected = {
64-
results: [
65-
{
66-
className: 'HasAllPOD',
67-
fields: {
68-
//Default fields
69-
ACL: {type: 'ACL'},
70-
createdAt: {type: 'Date'},
71-
updatedAt: {type: 'Date'},
72-
objectId: {type: 'String'},
73-
//Custom fields
74-
aNumber: {type: 'Number'},
75-
aString: {type: 'String'},
76-
aBool: {type: 'Boolean'},
77-
aDate: {type: 'Date'},
78-
aObject: {type: 'Object'},
79-
aArray: {type: 'Array'},
80-
aGeoPoint: {type: 'GeoPoint'},
81-
aFile: {type: 'File'}
82-
},
83-
},
84-
{
85-
className: 'HasPointersAndRelations',
86-
fields: {
87-
//Default fields
88-
ACL: {type: 'ACL'},
89-
createdAt: {type: 'Date'},
90-
updatedAt: {type: 'Date'},
91-
objectId: {type: 'String'},
92-
//Custom fields
93-
aPointer: {
94-
type: 'Pointer',
95-
targetClass: 'HasAllPOD',
96-
},
97-
aRelation: {
98-
type: 'Relation',
99-
targetClass: 'HasAllPOD',
100-
},
101-
},
102-
}
103-
]
104-
};
105-
expect(body).toEqual(expected);
106-
done();
107-
})
130+
it('responds with a single schema', done => {
131+
var obj = hasAllPODobject();
132+
obj.save().then(() => {
133+
request.get({
134+
url: 'http://localhost:8378/1/schemas/HasAllPOD',
135+
json: true,
136+
headers: {
137+
'X-Parse-Application-Id': 'test',
138+
'X-Parse-Master-Key': 'test',
139+
},
140+
}, (error, response, body) => {
141+
expect(body).toEqual(expectedResponseForHasAllPOD);
142+
done();
108143
});
144+
});
145+
});
146+
147+
it('treats class names case sensitively', done => {
148+
var obj = hasAllPODobject();
149+
obj.save().then(() => {
150+
request.get({
151+
url: 'http://localhost:8378/1/schemas/HASALLPOD',
152+
json: true,
153+
headers: {
154+
'X-Parse-Application-Id': 'test',
155+
'X-Parse-Master-Key': 'test',
156+
},
157+
}, (error, response, body) => {
158+
expect(response.statusCode).toEqual(400);
159+
expect(body).toEqual({
160+
code: 103,
161+
error: 'class HASALLPOD does not exist',
162+
});
163+
done();
164+
});
165+
});
109166
});
110167
});

0 commit comments

Comments
 (0)