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,33 +1,28 @@
"use strict"
const Parse = require("parse/node");
const request = require('request');
const rp = require('request-promise');
const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').InMemoryCacheAdapter;
describe('Cloud Code', () => {
it('can load absolute cloud code file', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test',
cloud: __dirname + '/cloud/cloudCodeRelativeFile.js'
});
Parse.Cloud.run('cloudCodeInFile', {}, result => {
expect(result).toEqual('It is possible to define cloud code in a file.');
done();
});
reconfigureServer({ cloud: __dirname + '/cloud/cloudCodeRelativeFile.js' })
.then(() => {
Parse.Cloud.run('cloudCodeInFile', {}, result => {
expect(result).toEqual('It is possible to define cloud code in a file.');
done();
});
})
});
it('can load relative cloud code file', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test',
cloud: './spec/cloud/cloudCodeAbsoluteFile.js'
});
Parse.Cloud.run('cloudCodeInFile', {}, result => {
expect(result).toEqual('It is possible to define cloud code in a file.');
done();
});
reconfigureServer({ cloud: './spec/cloud/cloudCodeAbsoluteFile.js' })
.then(() => {
Parse.Cloud.run('cloudCodeInFile', {}, result => {
expect(result).toEqual('It is possible to define cloud code in a file.');
done();
});
})
});
it('can create functions', done => {
@@ -568,67 +563,75 @@ describe('Cloud Code', () => {
});
it('clears out the user cache for all sessions when the user is changed', done => {
let session1;
let session2;
let user;
const cacheAdapter = new InMemoryCacheAdapter({ ttl: 100000000 });
setServerConfiguration(Object.assign({}, defaultConfiguration, { cacheAdapter: cacheAdapter }));
Parse.Cloud.define('checkStaleUser', (request, response) => {
response.success(request.user.get('data'));
});
reconfigureServer({ cacheAdapter })
.then(() => {
Parse.Cloud.define('checkStaleUser', (request, response) => {
response.success(request.user.get('data'));
});
let user = new Parse.User();
user.set('username', 'test');
user.set('password', 'moon-y');
user.set('data', 'first data');
user.signUp()
user = new Parse.User();
user.set('username', 'test');
user.set('password', 'moon-y');
user.set('data', 'first data');
return user.signUp();
})
.then(user => {
let session1 = user.getSessionToken();
request.get({
url: 'http://localhost:8378/1/login?username=test&password=moon-y',
session1 = user.getSessionToken();
return rp({
uri: 'http://localhost:8378/1/login?username=test&password=moon-y',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
},
}, (error, response, body) => {
let session2 = body.sessionToken;
})
})
.then(body => {
session2 = body.sessionToken;
//Ensure both session tokens are in the cache
Parse.Cloud.run('checkStaleUser')
.then(() => {
request.post({
url: 'http://localhost:8378/1/functions/checkStaleUser',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Session-Token': session2,
}
}, (error, response, body) => {
Parse.Promise.all([cacheAdapter.get('test:user:' + session1), cacheAdapter.get('test:user:' + session2)])
.then(cachedVals => {
expect(cachedVals[0].objectId).toEqual(user.id);
expect(cachedVals[1].objectId).toEqual(user.id);
//Ensure both session tokens are in the cache
return Parse.Cloud.run('checkStaleUser')
})
.then(() => rp({
method: 'POST',
uri: 'http://localhost:8378/1/functions/checkStaleUser',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Session-Token': session2,
}
}))
.then(() => Parse.Promise.all([cacheAdapter.get('test:user:' + session1), cacheAdapter.get('test:user:' + session2)]))
.then(cachedVals => {
expect(cachedVals[0].objectId).toEqual(user.id);
expect(cachedVals[1].objectId).toEqual(user.id);
//Change with session 1 and then read with session 2.
user.set('data', 'second data');
user.save()
.then(() => {
request.post({
url: 'http://localhost:8378/1/functions/checkStaleUser',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Session-Token': session2,
}
}, (error, response, body) => {
expect(body.result).toEqual('second data');
done();
})
});
});
});
});
});
//Change with session 1 and then read with session 2.
user.set('data', 'second data');
return user.save()
})
.then(() => rp({
method: 'POST',
uri: 'http://localhost:8378/1/functions/checkStaleUser',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Session-Token': session2,
}
}))
.then(body => {
expect(body.result).toEqual('second data');
done();
})
.catch(error => {
fail(JSON.stringify(error));
done();
});
});

View File

@@ -1,23 +0,0 @@
'use strict';
let DatabaseAdapter = require('../src/DatabaseAdapter');
describe('DatabaseAdapter', () => {
it('options and URI are available to adapter', done => {
DatabaseAdapter.setAppDatabaseURI('optionsTest', 'mongodb://localhost:27017/optionsTest');
DatabaseAdapter.setAppDatabaseOptions('optionsTest', {foo: "bar"});
let optionsTestDatabaseConnection = DatabaseAdapter.getDatabaseConnection('optionsTest');
expect(optionsTestDatabaseConnection).toEqual(jasmine.any(Object));
expect(optionsTestDatabaseConnection.adapter._mongoOptions).toEqual(jasmine.any(Object));
expect(optionsTestDatabaseConnection.adapter._mongoOptions.foo).toBe("bar");
DatabaseAdapter.setAppDatabaseURI('noOptionsTest', 'mongodb://localhost:27017/noOptionsTest');
let noOptionsTestDatabaseConnection = DatabaseAdapter.getDatabaseConnection('noOptionsTest');
expect(noOptionsTestDatabaseConnection).toEqual(jasmine.any(Object));
expect(noOptionsTestDatabaseConnection.adapter._mongoOptions).toEqual(jasmine.any(Object));
done();
});
});

View File

@@ -1,18 +0,0 @@
'use strict';
let DatabaseController = require('../src/Controllers/DatabaseController');
let MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
describe('DatabaseController', () => {
it('can be constructed', done => {
let adapter = new MongoStorageAdapter({
uri: 'mongodb://localhost:27017/test',
collectionPrefix: 'test_',
});
let databaseController = new DatabaseController(adapter);
databaseController.connect().then(done, error => {
console.log('error', error.stack);
fail();
});
});
});

View File

@@ -52,9 +52,9 @@ describe('error logs', () => {
describe('verbose logs', () => {
it("mask sensitive information in _User class", (done) => {
let customConfig = Object.assign({}, defaultConfiguration, {verbose: true});
setServerConfiguration(customConfig);
createTestUser().then(() => {
reconfigureServer({ verbose: true })
.then(() => createTestUser())
.then(() => {
let fileLoggerAdapter = new FileLoggerAdapter();
return fileLoggerAdapter.query({
from: new Date(Date.now() - 500),

View File

@@ -28,26 +28,27 @@ describe('Parse.Push', () => {
}
}
setServerConfiguration({
return reconfigureServer({
appId: Parse.applicationId,
masterKey: Parse.masterKey,
serverURL: Parse.serverURL,
push: {
adapter: pushAdapter
}
})
.then(() => {
var installations = [];
while(installations.length != 10) {
var installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length)
installation.set("badge", installations.length);
installation.set("originalBadge", installations.length);
installation.set("deviceType", "ios");
installations.push(installation);
}
return Parse.Object.saveAll(installations);
});
var installations = [];
while(installations.length != 10) {
var installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length)
installation.set("badge", installations.length);
installation.set("originalBadge", installations.length);
installation.set("deviceType", "ios");
installations.push(installation);
}
return Parse.Object.saveAll(installations);
}
it('should properly send push', (done) => {
@@ -110,7 +111,7 @@ describe('Parse.Push', () => {
'X-Parse-Application-Id': 'test',
},
}, (error, response, body) => {
expect(body.results.length).toEqual(0);
expect(body.error).toEqual('unauthorized');
done();
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -3,9 +3,14 @@
'use strict';
var DatabaseAdapter = require('../src/DatabaseAdapter');
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
var request = require('request');
const Parse = require("parse/node");
let Config = require('../src/Config');
let defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
var TestUtils = require('../src/index').TestUtils;
const requiredUserFields = { fields: Object.assign({}, defaultColumns._Default, defaultColumns._User) };
describe('miscellaneous', function() {
it('create a GameScore object', function(done) {
@@ -45,14 +50,172 @@ describe('miscellaneous', function() {
});
});
it('fail to create a duplicate username', function(done) {
createTestUser(function(data) {
createTestUser(function(data) {
fail('Should not have been able to save duplicate username.');
}, function(error) {
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
it('fail to create a duplicate username', done => {
let numCreated = 0;
let numFailed = 0;
let p1 = createTestUser();
p1.then(user => {
numCreated++;
expect(numCreated).toEqual(1);
})
.catch(error => {
numFailed++;
expect(numFailed).toEqual(1);
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
});
let p2 = createTestUser();
p2.then(user => {
numCreated++;
expect(numCreated).toEqual(1);
})
.catch(error => {
numFailed++;
expect(numFailed).toEqual(1);
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
});
Parse.Promise.when([p1, p2])
.then(() => {
fail('one of the users should not have been created');
done();
})
.catch(done);
});
it('ensure that email is uniquely indexed', done => {
let numCreated = 0;
let numFailed = 0;
let user1 = new Parse.User();
user1.setPassword('asdf');
user1.setUsername('u1');
user1.setEmail('dupe@dupe.dupe');
let p1 = user1.signUp();
p1.then(user => {
numCreated++;
expect(numCreated).toEqual(1);
}, error => {
numFailed++;
expect(numFailed).toEqual(1);
expect(error.code).toEqual(Parse.Error.EMAIL_TAKEN);
});
let user2 = new Parse.User();
user2.setPassword('asdf');
user2.setUsername('u2');
user2.setEmail('dupe@dupe.dupe');
let p2 = user2.signUp();
p2.then(user => {
numCreated++;
expect(numCreated).toEqual(1);
}, error => {
numFailed++;
expect(numFailed).toEqual(1);
expect(error.code).toEqual(Parse.Error.EMAIL_TAKEN);
});
Parse.Promise.when([p1, p2])
.then(() => {
fail('one of the users should not have been created');
done();
})
.catch(done);
});
it('ensure that if people already have duplicate users, they can still sign up new users', done => {
reconfigureServer({})
// Remove existing data to clear out unique index
.then(TestUtils.destroyAllDataPermanently)
.then(() => {
let adapter = new MongoStorageAdapter({
uri: 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase',
collectionPrefix: 'test_',
});
adapter.createObject('_User', { objectId: 'x', username: 'u' }, requiredUserFields)
.then(() => adapter.createObject('_User', { objectId: 'y', username: 'u' }, requiredUserFields))
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('zxcv');
return user.signUp();
})
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('u');
user.signUp()
.catch(error => {
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
done();
});
})
.catch(error => {
fail(JSON.stringify(error));
done();
});
}, () => {
fail('destroyAllDataPermanently failed')
done();
});
});
it('ensure that if people already have duplicate emails, they can still sign up new users', done => {
reconfigureServer({})
// Wipe out existing database with unique index so we can create a duplicate user
.then(TestUtils.destroyAllDataPermanently)
.then(() => {
let adapter = new MongoStorageAdapter({
uri: 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase',
collectionPrefix: 'test_',
});
adapter.createObject('_User', { objectId: 'x', email: 'a@b.c' }, requiredUserFields)
.then(() => adapter.createObject('_User', { objectId: 'y', email: 'a@b.c' }, requiredUserFields))
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('qqq');
user.setEmail('unique@unique.unique');
return user.signUp();
})
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('www');
user.setEmail('a@b.c');
user.signUp()
.catch(error => {
expect(error.code).toEqual(Parse.Error.EMAIL_TAKEN);
done();
});
})
.catch(error => {
fail(JSON.stringify(error));
done();
});
});
});
it('ensure that if you try to sign up a user with a unique username and email, but duplicates in some other field that has a uniqueness constraint, you get a regular duplicate value error', done => {
let config = new Config('test');
config.database.adapter.ensureUniqueness('_User', ['randomField'], requiredUserFields)
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('1');
user.setEmail('1@b.c');
user.set('randomField', 'a');
return user.signUp()
})
.then(() => {
let user = new Parse.User();
user.setPassword('asdf');
user.setUsername('2');
user.setEmail('2@b.c');
user.set('randomField', 'a');
return user.signUp()
})
.catch(error => {
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
done();
});
});
@@ -89,8 +252,8 @@ describe('miscellaneous', function() {
return Parse.User.logIn('test', 'moon-y');
}).then((user) => {
expect(user.get('foo')).toEqual(2);
Parse.User.logOut();
done();
Parse.User.logOut()
.then(done);
}, (error) => {
fail(error);
done();
@@ -202,14 +365,14 @@ describe('miscellaneous', function() {
obj.set('foo', 'bar');
return obj.save();
}).then(() => {
var db = DatabaseAdapter.getDatabaseConnection(appId, 'test_');
return db.adapter.find('TestObject', {}, { fields: {} }, {});
let config = new Config(appId);
return config.database.adapter.find('TestObject', {}, { fields: {} }, {});
}).then((results) => {
expect(results.length).toEqual(1);
expect(results[0]['foo']).toEqual('bar');
done();
}).fail(err => {
fail(err);
}).fail(error => {
fail(JSON.stringify(error));
done();
})
});
@@ -1119,27 +1282,6 @@ describe('miscellaneous', function() {
});
});
it('fail when create duplicate value in unique field', (done) => {
let obj = new Parse.Object('UniqueField');
obj.set('unique', 'value');
obj.save().then(() => {
expect(obj.id).not.toBeUndefined();
let config = new Config('test');
return config.database.adapter.adaptiveCollection('UniqueField')
}).then(collection => {
return collection._mongoCollection.createIndex({ 'unique': 1 }, { unique: true })
}).then(() => {
let obj = new Parse.Object('UniqueField');
obj.set('unique', 'value');
return obj.save()
}).then(() => {
return Promise.reject();
}, error => {
expect(error.code === Parse.Error.DUPLICATE_VALUE);
done();
});
});
it('doesnt convert interior keys of objects that use special names', done => {
let obj = new Parse.Object('Obj');
obj.set('val', { createdAt: 'a', updatedAt: 1 });

View File

@@ -1,3 +1,4 @@
"use strict";
/* global describe, it, expect, fail, Parse */
var request = require('request');
var triggers = require('../src/triggers');
@@ -13,7 +14,7 @@ var hookServerURL = "http://localhost:"+port;
var app = express();
app.use(bodyParser.json({ 'type': '*/*' }))
app.listen(12345);
let AppCache = require('../src/cache').AppCache;
describe('Hooks', () => {
@@ -257,7 +258,7 @@ describe('Hooks', () => {
expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).toBeUndefined();
expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).toBeUndefined();
}
const hooksController = new HooksController(Parse.applicationId);
const hooksController = new HooksController(Parse.applicationId, AppCache.get('test').databaseController);
return hooksController.load()
}, (err) => {
console.error(err);
@@ -347,28 +348,30 @@ describe('Hooks', () => {
});
it("should not pass X-Parse-Webhook-Key if not provided", (done) => {
setServerConfiguration(Object.assign({}, defaultConfiguration, { webhookKey: undefined }));
app.post("/ExpectingKeyAlso", function(req, res) {
if (req.get('X-Parse-Webhook-Key') === 'hook') {
res.json({success: "correct key provided"});
} else {
res.json({error: "incorrect key provided"});
}
});
reconfigureServer({ webhookKey: undefined })
.then(() => {
app.post("/ExpectingKeyAlso", function(req, res) {
if (req.get('X-Parse-Webhook-Key') === 'hook') {
res.json({success: "correct key provided"});
} else {
res.json({error: "incorrect key provided"});
}
});
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKeyAlso").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => {
console.error(err);
fail("Should not fail creating a function");
done();
}).then(function(res){
fail("Should not succeed calling that function");
done();
}, (err) => {
expect(err.code).toBe(141);
expect(err.message).toEqual("incorrect key provided");
done();
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKeyAlso").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => {
console.error(err);
fail("Should not fail creating a function");
done();
}).then(function(res){
fail("Should not succeed calling that function");
done();
}, (err) => {
expect(err.code).toBe(141);
expect(err.message).toEqual("incorrect key provided");
done();
});
});
});

View File

@@ -5,13 +5,12 @@
let auth = require('../src/Auth');
let cache = require('../src/cache');
let Config = require('../src/Config');
let DatabaseAdapter = require('../src/DatabaseAdapter');
let Parse = require('parse/node').Parse;
let rest = require('../src/rest');
let request = require("request");
let config = new Config('test');
let database = DatabaseAdapter.getDatabaseConnection('test', 'test_');
let database = config.database;
let defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
const installationSchema = { fields: Object.assign({}, defaultColumns._Default, defaultColumns._Installation) };

View File

@@ -696,6 +696,7 @@ describe('Parse.Relation testing', () => {
admins.first({ useMasterKey: true })
.then(user => {
if (user) {
response.success(user);
done();
} else {
fail('Should have found admin user, found nothing instead');

View File

@@ -2384,35 +2384,32 @@ describe('Parse.User testing', () => {
});
it('should not revoke session tokens if the server is configures to not revoke session tokens', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
masterKey: 'test',
revokeSessionOnPasswordReset: false,
})
request.post({
url: 'http://localhost:8378/1/classes/_User',
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: {authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}}
}, (err, res, body) => {
Parse.User.become(body.sessionToken)
.then(user => {
let obj = new Parse.Object('TestObject');
obj.setACL(new Parse.ACL(user));
return obj.save()
.then(() => {
// Change password, revoking session
user.set('username', 'no longer anonymous');
user.set('password', 'password');
return user.save()
reconfigureServer({ revokeSessionOnPasswordReset: false })
.then(() => {
request.post({
url: 'http://localhost:8378/1/classes/_User',
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: {authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}}
}, (err, res, body) => {
Parse.User.become(body.sessionToken)
.then(user => {
let obj = new Parse.Object('TestObject');
obj.setACL(new Parse.ACL(user));
return obj.save()
.then(() => {
// Change password, revoking session
user.set('username', 'no longer anonymous');
user.set('password', 'password');
return user.save()
})
.then(() => obj.fetch())
// fetch should succeed as we still have our session token
.then(done, fail);
})
.then(() => obj.fetch())
// fetch should succeed as we still have our session token
.then(done, fail);
})
});
});
})
});

View File

@@ -194,7 +194,7 @@ describe('Pointer Permissions', () => {
})
});
it('should handle multiple writeUserFields', (done) => {
it('should handle multiple writeUserFields', done => {
let config = new Config(Parse.applicationId);
let user = new Parse.User();
let user2 = new Parse.User();
@@ -207,27 +207,24 @@ describe('Pointer Permissions', () => {
password: 'password'
});
let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => {
Parse.Object.saveAll([user, user2])
.then(() => {
obj.set('owner', user);
obj.set('otherOwner', user2);
return obj.save();
}).then(() => {
return config.database.loadSchema().then((schema) => {
return schema.updateClass('AnObject', {}, {find: {"*": true},writeUserFields: ['owner', 'otherOwner']});
});
}).then(() => {
return Parse.User.logIn('user1', 'password');
}).then(() => {
return obj.save({hello: 'fromUser1'});
}).then(() => {
return Parse.User.logIn('user2', 'password');
}).then(() => {
return obj.save({hello: 'fromUser2'});
}).then(() => {
Parse.User.logOut();
})
.then(() => config.database.loadSchema())
.then(schema => schema.updateClass('AnObject', {}, {find: {"*": true},writeUserFields: ['owner', 'otherOwner']}))
.then(() => Parse.User.logIn('user1', 'password'))
.then(() => obj.save({hello: 'fromUser1'}))
.then(() => Parse.User.logIn('user2', 'password'))
.then(() => obj.save({hello: 'fromUser2'}))
.then(() => Parse.User.logOut())
.then(() => {
let q = new Parse.Query('AnObject');
return q.first();
}).then((result) => {
})
.then(result => {
expect(result.get('hello')).toBe('fromUser2');
done();
}).catch(err => {

View File

@@ -2,43 +2,33 @@
var request = require('request');
describe("public API", () => {
beforeEach(done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
publicServerURL: 'http://localhost:8378/1'
});
done();
})
it("should get invalid_link.html", (done) => {
request('http://localhost:8378/1/apps/invalid_link.html', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(200);
done();
});
});
it("should get choose_password", (done) => {
request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(200);
done();
});
reconfigureServer({
appName: 'unused',
publicServerURL: 'http://localhost:8378/1',
})
.then(() => {
request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(200);
done();
});
})
});
it("should get verify_email_success.html", (done) => {
request('http://localhost:8378/1/apps/verify_email_success.html', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(200);
done();
});
});
it("should get password_reset_success.html", (done) => {
request('http://localhost:8378/1/apps/password_reset_success.html', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(200);
@@ -49,19 +39,8 @@ describe("public API", () => {
describe("public API without publicServerURL", () => {
beforeEach(done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
appName: 'unused',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
});
done();
reconfigureServer({ appName: 'unused' })
.then(done, fail);
})
it("should get 404 on verify_email", (done) => {
request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse, body) => {
@@ -69,14 +48,14 @@ describe("public API without publicServerURL", () => {
done();
});
});
it("should get 404 choose_password", (done) => {
request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(404);
done();
});
});
it("should get 404 on request_password_reset", (done) => {
request('http://localhost:8378/1/apps/test/request_password_reset', (err, httpResponse, body) => {
expect(httpResponse.statusCode).toBe(404);

View File

@@ -3,13 +3,12 @@
var auth = require('../src/Auth');
var cache = require('../src/cache');
var Config = require('../src/Config');
var DatabaseAdapter = require('../src/DatabaseAdapter');
var Parse = require('parse/node').Parse;
var rest = require('../src/rest');
var request = require('request');
var config = new Config('test');
var database = DatabaseAdapter.getDatabaseConnection('test', 'test_');
let database = config.database;
describe('rest create', () => {
it('handles _id', done => {

View File

@@ -1,3 +1,4 @@
'use strict'
// These tests check the "find" functionality of the REST API.
var auth = require('../src/Auth');
var cache = require('../src/cache');
@@ -7,10 +8,8 @@ var rest = require('../src/rest');
var querystring = require('querystring');
var request = require('request');
var DatabaseAdapter = require('../src/DatabaseAdapter');
var database = DatabaseAdapter.getDatabaseConnection('test', 'test_');
var config = new Config('test');
let database = config.database;
var nobody = auth.nobody(config);
describe('rest query', () => {

103
spec/Uniqueness.spec.js Normal file
View File

@@ -0,0 +1,103 @@
'use strict';
var request = require('request');
const Parse = require("parse/node");
let Config = require('../src/Config');
describe('Uniqueness', function() {
it('fail when create duplicate value in unique field', done => {
let obj = new Parse.Object('UniqueField');
obj.set('unique', 'value');
obj.save().then(() => {
expect(obj.id).not.toBeUndefined();
let config = new Config('test');
return config.database.adapter.ensureUniqueness('UniqueField', ['unique'], { fields: { unique: { __type: 'String' } } })
})
.then(() => {
let obj = new Parse.Object('UniqueField');
obj.set('unique', 'value');
return obj.save()
}).then(() => {
fail('Saving duplicate field should have failed');
done();
}, error => {
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
done();
});
});
it('unique indexing works on pointer fields', done => {
let obj = new Parse.Object('UniquePointer');
obj.save({ string: 'who cares' })
.then(() => obj.save({ ptr: obj }))
.then(() => {
let config = new Config('test');
return config.database.adapter.ensureUniqueness('UniquePointer', ['ptr'], { fields: {
string: { __type: 'String' },
ptr: { __type: 'Pointer', targetClass: 'UniquePointer' }
} });
})
.then(() => {
let newObj = new Parse.Object('UniquePointer')
newObj.set('ptr', obj)
return newObj.save()
})
.then(() => {
fail('save should have failed due to duplicate value');
done();
})
.catch(error => {
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
done();
});
});
it('fails when attempting to ensure uniqueness of fields that are not currently unique', done => {
let o1 = new Parse.Object('UniqueFail');
o1.set('key', 'val');
let o2 = new Parse.Object('UniqueFail');
o2.set('key', 'val');
Parse.Object.saveAll([o1, o2])
.then(() => {
let config = new Config('test');
return config.database.adapter.ensureUniqueness('UniqueFail', ['key'], { fields: { key: { __type: 'String' } } });
})
.catch(error => {
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
done();
});
});
it('can do compound uniqueness', done => {
let config = new Config('test');
config.database.adapter.ensureUniqueness('CompoundUnique', ['k1', 'k2'], { fields: { k1: { __type: 'String' }, k2: { __type: 'String' } } })
.then(() => {
let o1 = new Parse.Object('CompoundUnique');
o1.set('k1', 'v1');
o1.set('k2', 'v2');
return o1.save();
})
.then(() => {
let o2 = new Parse.Object('CompoundUnique');
o2.set('k1', 'v1');
o2.set('k2', 'not a dupe');
return o2.save();
})
.then(() => {
let o3 = new Parse.Object('CompoundUnique');
o3.set('k1', 'not a dupe');
o3.set('k2', 'v2');
return o3.save();
})
.then(() => {
let o4 = new Parse.Object('CompoundUnique');
o4.set('k1', 'v1');
o4.set('k2', 'v2');
return o4.save();
})
.catch(error => {
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
done();
});
});
});

View File

@@ -6,17 +6,8 @@ let Config = require("../src/Config");
describe("Custom Pages Configuration", () => {
it("should set the custom pages", (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',
customPages: {
invalidLink: "myInvalidLink",
verifyEmailSuccess: "myVerifyEmailSuccess",
@@ -24,17 +15,17 @@ describe("Custom Pages Configuration", () => {
passwordResetSuccess: "myPasswordResetSuccess"
},
publicServerURL: "https://my.public.server.com/1"
})
.then(() => {
var config = new Config("test");
expect(config.invalidLinkURL).toEqual("myInvalidLink");
expect(config.verifyEmailSuccessURL).toEqual("myVerifyEmailSuccess");
expect(config.choosePasswordURL).toEqual("myChoosePassword");
expect(config.passwordResetSuccessURL).toEqual("myPasswordResetSuccess");
expect(config.verifyEmailURL).toEqual("https://my.public.server.com/1/apps/test/verify_email");
expect(config.requestResetPasswordURL).toEqual("https://my.public.server.com/1/apps/test/request_password_reset");
done();
});
var config = new Config("test");
expect(config.invalidLinkURL).toEqual("myInvalidLink");
expect(config.verifyEmailSuccessURL).toEqual("myVerifyEmailSuccess");
expect(config.choosePasswordURL).toEqual("myChoosePassword");
expect(config.passwordResetSuccessURL).toEqual("myPasswordResetSuccess");
expect(config.verifyEmailURL).toEqual("https://my.public.server.com/1/apps/test/verify_email");
expect(config.requestResetPasswordURL).toEqual("https://my.public.server.com/1/apps/test/request_password_reset");
done();
});
});
@@ -45,39 +36,32 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}
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: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.setEmail('testIfEnabled@parse.com');
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
user.fetch()
.then(() => {
expect(user.get('emailVerified')).toEqual(false);
})
.then(() => {
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.setEmail('testIfEnabled@parse.com');
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
user.fetch()
.then(() => {
expect(user.get('emailVerified')).toEqual(false);
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
}
});
});
});
@@ -87,38 +71,31 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}
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: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then(() => {
expect(user.get('emailVerified')).toEqual(undefined);
})
.then(() => {
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then(() => {
expect(user.get('emailVerified')).toEqual(undefined);
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
}
});
});
});
@@ -128,47 +105,40 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}
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: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then((user) => {
user.set("email", "testWhenUpdating@parse.com");
return user.save();
}).then((user) => {
return user.fetch();
}).then(() => {
expect(user.get('emailVerified')).toEqual(false);
// Wait as on update email, we need to fetch the username
setTimeout(function(){
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
done();
}, 200);
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
})
.then(() => {
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then((user) => {
user.set("email", "testWhenUpdating@parse.com");
return user.save();
}).then((user) => {
return user.fetch();
}).then(() => {
expect(user.get('emailVerified')).toEqual(false);
// Wait as on update email, we need to fetch the username
setTimeout(function(){
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
done();
}, 200);
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
});
});
});
@@ -178,51 +148,44 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}
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: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
spyOn(emailAdapter, 'sendVerificationEmail').and.callFake((options) => {
expect(options.link).not.toBeNull();
expect(options.link).not.toMatch(/token=undefined/);
Promise.resolve();
});
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then((user) => {
user.set("email", "testValidLinkWhenUpdating@parse.com");
return user.save();
}).then((user) => {
return user.fetch();
}).then(() => {
expect(user.get('emailVerified')).toEqual(false);
// Wait as on update email, we need to fetch the username
setTimeout(function(){
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
done();
}, 200);
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
})
.then(() => {
spyOn(emailAdapter, 'sendVerificationEmail').and.callFake((options) => {
expect(options.link).not.toBeNull();
expect(options.link).not.toMatch(/token=undefined/);
Promise.resolve();
});
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
expect(emailAdapter.sendVerificationEmail).not.toHaveBeenCalled();
user.fetch()
.then((user) => {
user.set("email", "testValidLinkWhenUpdating@parse.com");
return user.save();
}).then((user) => {
return user.fetch();
}).then(() => {
expect(user.get('emailVerified')).toEqual(false);
// Wait as on update email, we need to fetch the username
setTimeout(function(){
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
done();
}, 200);
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
});
});
});
@@ -242,60 +205,44 @@ describe("Email Verification", () => {
return Promise.resolve();
}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'My Cool App',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set("email", "testSendSimpleAdapter@parse.com");
user.signUp(null, {
success: function(user) {
expect(calls).toBe(1);
user.fetch()
.then((user) => {
return user.save();
}).then((user) => {
return Parse.User.requestPasswordReset("testSendSimpleAdapter@parse.com").catch((err) => {
fail('Should not fail requesting a password');
})
.then(() => {
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set("email", "testSendSimpleAdapter@parse.com");
user.signUp(null, {
success: function(user) {
expect(calls).toBe(1);
user.fetch()
.then((user) => {
return user.save();
}).then((user) => {
return Parse.User.requestPasswordReset("testSendSimpleAdapter@parse.com").catch((err) => {
fail('Should not fail requesting a password');
done();
})
}).then(() => {
expect(calls).toBe(2);
done();
})
}).then(() => {
expect(calls).toBe(2);
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
}
});
});
});
it('fails if you include an emailAdapter, set verifyUserEmails to false, dont set a publicServerURL, and try to send a password reset email (regression test for #1649)', 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: false,
emailAdapter: MockEmailAdapterWithOptions({
fromAddress: 'parse@example.com',
@@ -303,20 +250,21 @@ describe("Email Verification", () => {
domain: 'd',
}),
})
let user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com");
user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => {
console.log(result);
fail('sending password reset email should not have succeeded');
done();
}, error => {
expect(error.message).toEqual('An appName, publicServerURL, and emailAdapter are required for password reset functionality.')
done();
.then(() => {
let user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com");
user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => {
console.log(result);
fail('sending password reset email should not have succeeded');
done();
}, error => {
expect(error.message).toEqual('An appName, publicServerURL, and emailAdapter are required for password reset functionality.')
done();
});
});
});
@@ -326,37 +274,30 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}
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: false,
emailAdapter: emailAdapter,
});
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
user.fetch()
.then(() => {
expect(emailAdapter.sendVerificationEmail.calls.count()).toEqual(0);
expect(user.get('emailVerified')).toEqual(undefined);
})
.then(() => {
spyOn(emailAdapter, 'sendVerificationEmail');
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.signUp(null, {
success: function(user) {
user.fetch()
.then(() => {
expect(emailAdapter.sendVerificationEmail.calls.count()).toEqual(0);
expect(user.get('emailVerified')).toEqual(undefined);
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
});
},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
}
});
});
});
@@ -370,31 +311,24 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => {}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp(null, {
success: () => {},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
})
.then(() => {
var user = new Parse.User();
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp(null, {
success: () => {},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
});
});
})
@@ -421,39 +355,23 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => {}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
})
.then(() => {
user.setPassword("asdf");
user.setUsername("user");
user.set('email', 'user@parse.com');
user.signUp();
});
user.setPassword("asdf");
user.setUsername("user");
user.set('email', 'user@parse.com');
user.signUp();
});
it('redirects you to invalid link if you try to verify email incorrecly', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
sendVerificationEmail: () => Promise.resolve(),
@@ -461,28 +379,21 @@ describe("Email Verification", () => {
sendMail: () => {}
},
publicServerURL: "http://localhost:8378/1"
});
request.get('http://localhost:8378/1/apps/test/verify_email', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done()
})
.then(() => {
request.get('http://localhost:8378/1/apps/test/verify_email', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done()
});
});
});
it('redirects you to invalid link if you try to validate a nonexistant users email', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
sendVerificationEmail: () => Promise.resolve(),
@@ -490,13 +401,15 @@ describe("Email Verification", () => {
sendMail: () => {}
},
publicServerURL: "http://localhost:8378/1"
});
request.get('http://localhost:8378/1/apps/test/verify_email?token=asdfasdf&username=sadfasga', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done();
})
.then(() => {
request.get('http://localhost:8378/1/apps/test/verify_email?token=asdfasdf&username=sadfasga', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done();
});
});
});
@@ -519,30 +432,23 @@ describe("Email Verification", () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => {}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp(null, {
success: () => {},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
})
.then(() => {
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp(null, {
success: () => {},
error: function(userAgain, error) {
fail('Failed to save user');
done();
}
});
});
});
});
@@ -570,47 +476,31 @@ describe("Password Reset", () => {
},
sendMail: () => {}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
user.setPassword("asdf");
user.setUsername("zxcv+zxcv");
user.set('email', 'user@parse.com');
user.signUp().then(() => {
Parse.User.requestPasswordReset('user@parse.com', {
error: (err) => {
console.error(err);
fail("Should not fail requesting a password");
done();
}
})
.then(() => {
user.setPassword("asdf");
user.setUsername("zxcv+zxcv");
user.set('email', 'user@parse.com');
user.signUp().then(() => {
Parse.User.requestPasswordReset('user@parse.com', {
error: (err) => {
console.error(err);
fail("Should not fail requesting a password");
done();
}
});
});
});
});
it('redirects you to invalid link if you try to request password for a nonexistant users email', done => {
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
sendVerificationEmail: () => Promise.resolve(),
@@ -618,13 +508,15 @@ describe("Password Reset", () => {
sendMail: () => {}
},
publicServerURL: "http://localhost:8378/1"
});
request.get('http://localhost:8378/1/apps/test/request_password_reset?token=asdfasdf&username=sadfasga', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done();
})
.then(() => {
request.get('http://localhost:8378/1/apps/test/request_password_reset?token=asdfasdf&username=sadfasga', {
followRedirect: false,
}, (error, response, body) => {
expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done();
});
});
});
@@ -688,33 +580,25 @@ describe("Password Reset", () => {
},
sendMail: () => {}
}
setServerConfiguration({
serverURL: 'http://localhost:8378/1',
appId: 'test',
reconfigureServer({
appName: 'emailing app',
javascriptKey: 'test',
dotNetKey: 'windows',
clientKey: 'client',
restAPIKey: 'rest',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
});
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp().then(() => {
Parse.User.requestPasswordReset('user@parse.com', {
error: (err) => {
console.error(err);
fail("Should not fail");
done();
}
})
.then(() => {
user.setPassword("asdf");
user.setUsername("zxcv");
user.set('email', 'user@parse.com');
user.signUp().then(() => {
Parse.User.requestPasswordReset('user@parse.com', {
error: (err) => {
console.error(err);
fail("Should not fail");
done();
}
});
});
});
});
})

View File

@@ -1,6 +1,7 @@
"use strict"
// Sets up a Parse API server for testing.
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;
jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 3000;
var cache = require('../src/cache').default;
var DatabaseAdapter = require('../src/DatabaseAdapter');
@@ -10,13 +11,23 @@ var ParseServer = require('../src/index').ParseServer;
var path = require('path');
var TestUtils = require('../src/index').TestUtils;
var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
const GridStoreAdapter = require('../src/Adapters/Files/GridStoreAdapter').GridStoreAdapter;
var databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
var port = 8378;
let mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
let mongoAdapter = new MongoStorageAdapter({
uri: mongoURI,
collectionPrefix: 'test_',
})
let gridStoreAdapter = new GridStoreAdapter(mongoURI);
// Default server configuration for tests.
var defaultConfiguration = {
databaseURI: databaseURI,
databaseAdapter: mongoAdapter,
filesAdapter: gridStoreAdapter,
serverURL: 'http://localhost:' + port + '/1',
appId: 'test',
javascriptKey: 'test',
@@ -25,14 +36,13 @@ var defaultConfiguration = {
restAPIKey: 'rest',
webhookKey: 'hook',
masterKey: 'test',
collectionPrefix: 'test_',
fileKey: 'test',
push: {
'ios': {
cert: 'prodCert.pem',
key: 'prodKey.pem',
production: true,
bundleId: 'bundleId'
bundleId: 'bundleId',
}
},
oauth: { // Override the facebook provider
@@ -43,33 +53,45 @@ var defaultConfiguration = {
},
};
let openConnections = {};
// Set up a default API server for testing with default configuration.
var api = new ParseServer(defaultConfiguration);
var app = express();
app.use('/1', api);
var server = app.listen(port);
server.on('connection', connection => {
let key = `${connection.remoteAddress}:${connection.remotePort}`;
openConnections[key] = connection;
connection.on('close', () => { delete openConnections[key] });
});
// Prevent reinitializing the server from clobbering Cloud Code
delete defaultConfiguration.cloud;
var currentConfiguration;
// Allows testing specific configurations of Parse Server
const setServerConfiguration = configuration => {
// the configuration hasn't changed
if (configuration === currentConfiguration) {
return;
}
DatabaseAdapter.clearDatabaseSettings();
currentConfiguration = configuration;
server.close();
cache.clear();
app = express();
api = new ParseServer(configuration);
app.use('/1', api);
server = app.listen(port);
};
const reconfigureServer = changedConfiguration => {
return new Promise((resolve, reject) => {
server.close(() => {
try {
let newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, {
__indexBuildCompletionCallbackForTests: indexBuildPromise => indexBuildPromise.then(resolve, reject)
});
cache.clear();
app = express();
api = new ParseServer(newConfiguration);
app.use('/1', api);
var restoreServerConfiguration = () => setServerConfiguration(defaultConfiguration);
server = app.listen(port);
server.on('connection', connection => {
let key = `${connection.remoteAddress}:${connection.remotePort}`;
openConnections[key] = connection;
connection.on('close', () => { delete openConnections[key] });
});
} catch(error) {
reject(error);
}
});
});
}
// Set up a Parse client to talk to our test API server
var Parse = require('parse/node');
@@ -79,19 +101,35 @@ Parse.serverURL = 'http://localhost:' + port + '/1';
// TODO: update tests to work in an A+ way
Parse.Promise.disableAPlusCompliant();
beforeEach(function(done) {
restoreServerConfiguration();
Parse.initialize('test', 'test', 'test');
Parse.serverURL = 'http://localhost:' + port + '/1';
Parse.User.enableUnsafeCurrentUser();
return TestUtils.destroyAllDataPermanently().then(done, fail);
beforeEach(done => {
try {
Parse.User.enableUnsafeCurrentUser();
} catch (error) {
if (error !== 'You need to call Parse.initialize before using Parse.') {
throw error;
}
}
TestUtils.destroyAllDataPermanently()
.catch(error => {
// For tests that connect to their own mongo, there won't be any data to delete.
if (error.message === 'ns not found' || error.message.startsWith('connect ECONNREFUSED')) {
return;
} else {
fail(error);
return;
}
})
.then(reconfigureServer)
.then(() => {
Parse.initialize('test', 'test', 'test');
Parse.serverURL = 'http://localhost:' + port + '/1';
done();
}, error => {
fail(JSON.stringify(error));
done();
})
});
var mongoAdapter = new MongoStorageAdapter({
collectionPrefix: defaultConfiguration.collectionPrefix,
uri: databaseURI,
})
afterEach(function(done) {
Parse.Cloud._removeAllHooks();
mongoAdapter.getAllSchemas()
@@ -111,11 +149,13 @@ afterEach(function(done) {
})
.then(() => Parse.User.logOut())
.then(() => {
return TestUtils.destroyAllDataPermanently();
}).then(() => {
if (Object.keys(openConnections).length > 0) {
fail('There were open connections to the server left after the test finished');
}
done();
}, (error) => {
console.log('error in clearData', error);
})
.catch(error => {
fail(JSON.stringify(error));
done();
});
});
@@ -243,14 +283,16 @@ function mockFacebook() {
facebook.validateAuthData = function(authData) {
if (authData.id === '8675309' && authData.access_token === 'jenny') {
return Promise.resolve();
} else {
throw undefined;
}
return Promise.reject();
};
facebook.validateAppId = function(appId, authData) {
if (authData.access_token === 'jenny') {
return Promise.resolve();
} else {
throw undefined;
}
return Promise.reject();
};
return facebook;
}
@@ -272,7 +314,7 @@ global.expectError = expectError;
global.arrayContains = arrayContains;
global.jequal = jequal;
global.range = range;
global.setServerConfiguration = setServerConfiguration;
global.reconfigureServer = reconfigureServer;
global.defaultConfiguration = defaultConfiguration;
// LiveQuery test setting

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);
});
});