Unique indexes (#1971)

* Add unique indexing

* Add unique indexing for username/email

* WIP

* Finish unique indexes

* Notes on how to upgrade to 2.3.0 safely

* index on unique-indexes: c454180 Revert "Log objects rather than JSON stringified objects (#1922)"

* reconfigure username/email tests

* Start dealing with test shittyness

* Remove tests for files that we are removing

* most tests passing

* fix failing test

* Make specific server config for tests async

* Fix more tests

* fix more tests

* Fix another test

* fix more tests

* Fix email validation

* move some stuff around

* Destroy server to ensure all connections are gone

* Fix broken cloud code

* Save callback to variable

* no need to delete non existant cloud

* undo

* Fix all tests where connections are left open after server closes.

* Fix issues caused by missing gridstore adapter

* Update guide for 2.3.0 and fix final tests

* use strict

* don't use features that won't work in node 4

* Fix syntax error

* Fix typos

* Add duplicate finding command

* Update 2.3.0.md
This commit is contained in:
Drew
2016-06-10 20:27:21 -07:00
committed by GitHub
parent 6415a35433
commit 7e868b2dcc
37 changed files with 1727 additions and 1517 deletions

View File

@@ -1,3 +1,4 @@
"use strict"
var request = require('request');
var parseServerPackage = require('../package.json');
var MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
@@ -5,12 +6,23 @@ var ParseServer = require("../src/index");
var Config = require('../src/Config');
var express = require('express');
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
describe('server', () => {
it('requires a master key and app id', done => {
expect(setServerConfiguration.bind(undefined, { })).toThrow('You must provide an appId!');
expect(setServerConfiguration.bind(undefined, { appId: 'myId' })).toThrow('You must provide a masterKey!');
expect(setServerConfiguration.bind(undefined, { appId: 'myId', masterKey: 'mk' })).toThrow('You must provide a serverURL!');
done();
reconfigureServer({ appId: undefined })
.catch(error => {
expect(error).toEqual('You must provide an appId!');
return reconfigureServer({ masterKey: undefined });
})
.catch(error => {
expect(error).toEqual('You must provide a masterKey!');
return reconfigureServer({ serverURL: undefined });
})
.catch(error => {
expect(error).toEqual('You must provide a serverURL!');
done();
});
});
it('support http basic authentication with masterkey', done => {
@@ -38,47 +50,29 @@ describe('server', () => {
});
it('fails if database is unreachable', done => {
setServerConfiguration({
databaseURI: 'mongodb://fake:fake@ds043605.mongolab.com:43605/drew3',
serverURL: 'http://localhost:8378/1',
appId: 'test',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
});
//Need to use rest api because saving via JS SDK results in fail() not getting called
request.post({
url: 'http://localhost:8378/1/classes/NewClass',
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
},
body: {},
json: true,
}, (error, response, body) => {
expect(response.statusCode).toEqual(500);
expect(body.code).toEqual(1);
expect(body.message).toEqual('Internal server error.');
done();
reconfigureServer({ databaseAdapter: new MongoStorageAdapter({ uri: 'mongodb://fake:fake@localhost:43605/drew3' }) })
.catch(() => {
//Need to use rest api because saving via JS SDK results in fail() not getting called
request.post({
url: 'http://localhost:8378/1/classes/NewClass',
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
},
body: {},
json: true,
}, (error, response, body) => {
expect(response.statusCode).toEqual(500);
expect(body.code).toEqual(1);
expect(body.message).toEqual('Internal server error.');
done();
});
});
});
it('can load email adapter via object', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: MockEmailAdapterWithOptions({
fromAddress: 'parse@example.com',
@@ -86,22 +80,12 @@ describe('server', () => {
domain: 'd',
}),
publicServerURL: 'http://localhost:8378/1'
});
done();
}).then(done, fail);
});
it('can load email adapter via class', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
class: MockEmailAdapterWithOptions,
@@ -112,22 +96,12 @@ describe('server', () => {
}
},
publicServerURL: 'http://localhost:8378/1'
});
done();
}).then(done, fail);
});
it('can load email adapter via module name', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
@@ -138,41 +112,25 @@ describe('server', () => {
}
},
publicServerURL: 'http://localhost:8378/1'
});
done();
}).then(done, fail);
});
it('can load email adapter via only module name', done => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: 'parse-server-simple-mailgun-adapter',
publicServerURL: 'http://localhost:8378/1'
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
})
.catch(error => {
expect(error).toEqual('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
});
});
it('throws if you initialize email adapter incorrecly', done => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
@@ -181,8 +139,11 @@ describe('server', () => {
}
},
publicServerURL: 'http://localhost:8378/1'
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
})
.catch(error => {
expect(error).toEqual('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
});
});
it('can report the server version', done => {
@@ -199,62 +160,71 @@ describe('server', () => {
})
});
it('can create a parse-server', done => {
var parseServer = new ParseServer.default({
it('can create a parse-server v1', done => {
var parseServer = new ParseServer.default(Object.assign({},
defaultConfiguration, {
appId: "aTestApp",
masterKey: "aTestMasterKey",
serverURL: "http://localhost:12666/parse",
databaseURI: 'mongodb://localhost:27017/aTestApp'
});
__indexBuildCompletionCallbackForTests: promise => {
promise
.then(() => {
expect(Parse.applicationId).toEqual("aTestApp");
var app = express();
app.use('/parse', parseServer.app);
expect(Parse.applicationId).toEqual("aTestApp");
var app = express();
app.use('/parse', parseServer.app);
var server = app.listen(12666);
var obj = new Parse.Object("AnObject");
var objId;
obj.save().then((obj) => {
objId = obj.id;
var q = new Parse.Query("AnObject");
return q.first();
}).then((obj) => {
expect(obj.id).toEqual(objId);
server.close();
done();
}).fail((err) => {
server.close();
done();
})
var server = app.listen(12666);
var obj = new Parse.Object("AnObject");
var objId;
obj.save().then((obj) => {
objId = obj.id;
var q = new Parse.Query("AnObject");
return q.first();
}).then((obj) => {
expect(obj.id).toEqual(objId);
server.close(done);
}).fail((err) => {
server.close(done);
})
});
}})
);
});
it('can create a parse-server', done => {
var parseServer = ParseServer.ParseServer({
it('can create a parse-server v2', done => {
let objId;
let server
let parseServer = ParseServer.ParseServer(Object.assign({},
defaultConfiguration, {
appId: "anOtherTestApp",
masterKey: "anOtherTestMasterKey",
serverURL: "http://localhost:12667/parse",
databaseURI: 'mongodb://localhost:27017/anotherTstApp'
});
__indexBuildCompletionCallbackForTests: promise => {
promise
.then(() => {
expect(Parse.applicationId).toEqual("anOtherTestApp");
let app = express();
app.use('/parse', parseServer);
expect(Parse.applicationId).toEqual("anOtherTestApp");
var app = express();
app.use('/parse', parseServer);
var server = app.listen(12667);
var obj = new Parse.Object("AnObject");
var objId;
obj.save().then((obj) => {
objId = obj.id;
var q = new Parse.Query("AnObject");
return q.first();
}).then((obj) => {
expect(obj.id).toEqual(objId);
server.close();
done();
}).fail((err) => {
server.close();
done();
})
server = app.listen(12667);
let obj = new Parse.Object("AnObject");
return obj.save()
})
.then(obj => {
objId = obj.id;
let q = new Parse.Query("AnObject");
return q.first();
})
.then(obj => {
expect(obj.id).toEqual(objId);
server.close(done);
})
.catch(error => {
fail(JSON.stringify(error))
done();
});
}}
));
});
it('has createLiveQueryServer', done => {
@@ -273,96 +243,65 @@ describe('server', () => {
});
it('properly gives publicServerURL when set', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test',
publicServerURL: 'https://myserver.com/1'
reconfigureServer({ publicServerURL: 'https://myserver.com/1' })
.then(() => {
var config = new Config('test', 'http://localhost:8378/1');
expect(config.mount).toEqual('https://myserver.com/1');
done();
});
var config = new Config('test', 'http://localhost:8378/1');
expect(config.mount).toEqual('https://myserver.com/1');
done();
});
it('properly removes trailing slash in mount', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test'
reconfigureServer({})
.then(() => {
var config = new Config('test', 'http://localhost:8378/1/');
expect(config.mount).toEqual('http://localhost:8378/1');
done();
});
var config = new Config('test', 'http://localhost:8378/1/');
expect(config.mount).toEqual('http://localhost:8378/1');
done();
});
it('should throw when getting invalid mount', done => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test',
publicServerURL: 'blabla:/some'
}) ).toThrow("publicServerURL should be a valid HTTPS URL starting with https://");
done();
reconfigureServer({ publicServerURL: 'blabla:/some' })
.catch(error => {
expect(error).toEqual('publicServerURL should be a valid HTTPS URL starting with https://')
done();
})
});
it('fails if the session length is not a number', (done) => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
masterKey: 'test',
sessionLength: 'test'
})).toThrow('Session length must be a valid number.');
done();
it('fails if the session length is not a number', done => {
reconfigureServer({ sessionLength: 'test' })
.catch(error => {
expect(error).toEqual('Session length must be a valid number.');
done();
});
});
it('fails if the session length is less than or equal to 0', (done) => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
masterKey: 'test',
sessionLength: '-33'
})).toThrow('Session length must be a value greater than 0.');
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
masterKey: 'test',
sessionLength: '0'
})).toThrow('Session length must be a value greater than 0.');
done();
it('fails if the session length is less than or equal to 0', done => {
reconfigureServer({ sessionLength: '-33' })
.catch(error => {
expect(error).toEqual('Session length must be a value greater than 0.');
return reconfigureServer({ sessionLength: '0' })
})
.catch(error => {
expect(error).toEqual('Session length must be a value greater than 0.');
done();
});
});
it('ignores the session length when expireInactiveSessions set to false', (done) => {
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
masterKey: 'test',
reconfigureServer({
sessionLength: '-33',
expireInactiveSessions: false
})).not.toThrow();
expect(() => setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
masterKey: 'test',
})
.then(() => reconfigureServer({
sessionLength: '0',
expireInactiveSessions: false
})).not.toThrow();
done();
}))
.then(done);
})
it('fails if you try to set revokeSessionOnPasswordReset to non-boolean', done => {
expect(() => setServerConfiguration({ revokeSessionOnPasswordReset: 'non-bool' })).toThrow();
done();
reconfigureServer({ revokeSessionOnPasswordReset: 'non-bool' })
.catch(done);
});
});