diff --git a/spec/ParseGlobalConfig.spec.js b/spec/ParseGlobalConfig.spec.js new file mode 100644 index 0000000000..0257fe9cbb --- /dev/null +++ b/spec/ParseGlobalConfig.spec.js @@ -0,0 +1,81 @@ + +var request = require('request'); +var Parse = require('parse/node').Parse; +var DatabaseAdapter = require('../src/DatabaseAdapter'); + +var database = DatabaseAdapter.getDatabaseConnection('test'); + +describe('a GlobalConfig', () => { + beforeEach(function(done) { + database.rawCollection('_GlobalConfig') + .then(coll => coll.updateOne({ '_id': 1}, { $set: { params: { companies: ['US', 'DK'] } } }, { upsert: true })) + .then(done()); + }); + + it('can be retrieved', (done) => { + request.get({ + url: 'http://localhost:8378/1/config', + json: true, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }, + }, (error, response, body) => { + expect(response.statusCode).toEqual(200); + expect(body.params.companies).toEqual(['US', 'DK']); + done(); + }); + }); + + it('can be updated when a master key exists', (done) => { + request.put({ + url: 'http://localhost:8378/1/config', + json: true, + body: { params: { companies: ['US', 'DK', 'SE'] } }, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test' + }, + }, (error, response, body) => { + expect(response.statusCode).toEqual(200); + expect(body.result).toEqual(true); + done(); + }); + }); + + it('fail to update if master key is missing', (done) => { + request.put({ + url: 'http://localhost:8378/1/config', + json: true, + body: { params: { companies: [] } }, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest' + }, + }, (error, response, body) => { + expect(response.statusCode).toEqual(401); + expect(body.error).toEqual('unauthorized'); + done(); + }); + }); + + it('failed getting config when it is missing', (done) => { + database.rawCollection('_GlobalConfig') + .then(coll => coll.deleteOne({ '_id': 1}, {}, {})) + .then(_ => { + request.get({ + url: 'http://localhost:8378/1/config', + json: true, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }, + }, (error, response, body) => { + expect(response.statusCode).toEqual(404); + expect(body.code).toEqual(Parse.Error.INVALID_KEY_NAME); + done(); + }); + }); + }); + +}); diff --git a/src/ExportAdapter.js b/src/ExportAdapter.js index 1676ccfb42..98705328e4 100644 --- a/src/ExportAdapter.js +++ b/src/ExportAdapter.js @@ -50,6 +50,10 @@ ExportAdapter.prototype.collection = function(className) { throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, 'invalid className: ' + className); } + return this.rawCollection(className); +}; + +ExportAdapter.prototype.rawCollection = function(className) { return this.connect().then(() => { return this.db.collection(this.collectionPrefix + className); }); diff --git a/src/global_config.js b/src/global_config.js new file mode 100644 index 0000000000..3dd1b5432e --- /dev/null +++ b/src/global_config.js @@ -0,0 +1,46 @@ +// global_config.js + +var Parse = require('parse/node').Parse, + PromiseRouter = require('./PromiseRouter'); + +var router = new PromiseRouter(); + +function getGlobalConfig(req) { + return req.config.database.rawCollection('_GlobalConfig') + .then(coll => coll.findOne({'_id': 1})) + .then(globalConfig => ({response: { params: globalConfig.params }})) + .catch(() => ({ + status: 404, + response: { + code: Parse.Error.INVALID_KEY_NAME, + error: 'config does not exist', + } + })); +} + +function updateGlobalConfig(req) { + if (!req.auth.isMaster) { + return Promise.resolve({ + status: 401, + response: {error: 'unauthorized'}, + }); + } + + return req.config.database.rawCollection('_GlobalConfig') + .then(coll => coll.findOneAndUpdate({ _id: 1 }, { $set: req.body })) + .then(response => { + return { response: { result: true } } + }) + .catch(() => ({ + status: 404, + response: { + code: Parse.Error.INVALID_KEY_NAME, + error: 'config cannot be updated', + } + })); +} + +router.route('GET', '/config', getGlobalConfig); +router.route('PUT', '/config', updateGlobalConfig); + +module.exports = router; diff --git a/src/index.js b/src/index.js index 73d48298d0..ef29ec7f39 100644 --- a/src/index.js +++ b/src/index.js @@ -121,6 +121,9 @@ function ParseServer(args) { router.merge(require('./installations')); router.merge(require('./functions')); router.merge(require('./schemas')); + if (process.env.PARSE_EXPERIMENTAL_CONFIG_ENABLED || process.env.TESTING) { + router.merge(require('./global_config')); + } batch.mountOnto(router);