Merge remote-tracking branch 'upstream/master' into encode_uri

This commit is contained in:
Taylor Stine
2016-02-02 07:14:53 -05:00
15 changed files with 229 additions and 59 deletions

17
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,17 @@
### Contributing to Parse Server
#### Pull Requests Welcome!
We really want Parse to be yours, to see it grow and thrive in the open source community.
##### Please Do's
* Please write tests to cover new methods.
* Please run the tests and make sure you didn't break anything.
##### Code of Conduct
This project adheres to the [Open Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code.
[code-of-conduct]: http://todogroup.org/opencodeofconduct/#Parse Server/fjm@fb.com

View File

@@ -20,6 +20,7 @@ var adapter = ExportAdapter;
var cache = require('./cache'); var cache = require('./cache');
var dbConnections = {}; var dbConnections = {};
var databaseURI = 'mongodb://localhost:27017/parse'; var databaseURI = 'mongodb://localhost:27017/parse';
var appDatabaseURIs = {};
function setAdapter(databaseAdapter) { function setAdapter(databaseAdapter) {
adapter = databaseAdapter; adapter = databaseAdapter;
@@ -29,11 +30,17 @@ function setDatabaseURI(uri) {
databaseURI = uri; databaseURI = uri;
} }
function setAppDatabaseURI(appId, uri) {
appDatabaseURIs[appId] = uri;
}
function getDatabaseConnection(appId) { function getDatabaseConnection(appId) {
if (dbConnections[appId]) { if (dbConnections[appId]) {
return dbConnections[appId]; return dbConnections[appId];
} }
dbConnections[appId] = new adapter(databaseURI, {
var dbURI = (appDatabaseURIs[appId] ? appDatabaseURIs[appId] : databaseURI);
dbConnections[appId] = new adapter(dbURI, {
collectionPrefix: cache.apps[appId]['collectionPrefix'] collectionPrefix: cache.apps[appId]['collectionPrefix']
}); });
dbConnections[appId].connect(); dbConnections[appId].connect();
@@ -44,5 +51,6 @@ module.exports = {
dbConnections: dbConnections, dbConnections: dbConnections,
getDatabaseConnection: getDatabaseConnection, getDatabaseConnection: getDatabaseConnection,
setAdapter: setAdapter, setAdapter: setAdapter,
setDatabaseURI: setDatabaseURI setDatabaseURI: setDatabaseURI,
setAppDatabaseURI: setAppDatabaseURI
}; };

View File

@@ -5,6 +5,7 @@
// Adapter classes must implement the following functions: // Adapter classes must implement the following functions:
// * create(config, filename, data) // * create(config, filename, data)
// * get(config, filename) // * get(config, filename)
// * location(config, req, filename)
// //
// Default is GridStoreAdapter, which requires mongo // Default is GridStoreAdapter, which requires mongo
// and for the API server to be using the ExportAdapter // and for the API server to be using the ExportAdapter

View File

@@ -4,6 +4,7 @@
// Requires the database adapter to be based on mongoclient // Requires the database adapter to be based on mongoclient
var GridStore = require('mongodb').GridStore; var GridStore = require('mongodb').GridStore;
var path = require('path');
// For a given config object, filename, and data, store a file // For a given config object, filename, and data, store a file
// Returns a promise // Returns a promise
@@ -32,7 +33,16 @@ function get(config, filename) {
}); });
} }
// Generates and returns the location of a file stored in GridStore for the
// given request and filename
function location(config, req, filename) {
return (req.protocol + '://' + req.get('host') +
path.dirname(req.originalUrl) + '/' + req.config.applicationId +
'/' + encodeURIComponent(filename));
}
module.exports = { module.exports = {
create: create, create: create,
get: get get: get,
location: location
}; };

View File

@@ -2,13 +2,14 @@
// that writes to the database. // that writes to the database.
// This could be either a "create" or an "update". // This could be either a "create" or an "update".
var crypto = require('crypto');
var deepcopy = require('deepcopy'); var deepcopy = require('deepcopy');
var rack = require('hat').rack(); var rack = require('hat').rack();
var Auth = require('./Auth'); var Auth = require('./Auth');
var cache = require('./cache'); var cache = require('./cache');
var Config = require('./Config'); var Config = require('./Config');
var crypto = require('./crypto'); var passwordCrypto = require('./password');
var facebook = require('./facebook'); var facebook = require('./facebook');
var Parse = require('parse/node'); var Parse = require('parse/node');
var triggers = require('./triggers'); var triggers = require('./triggers');
@@ -299,7 +300,7 @@ RestWrite.prototype.transformUser = function() {
if (this.query) { if (this.query) {
this.storage['clearSessions'] = true; this.storage['clearSessions'] = true;
} }
return crypto.hash(this.data.password).then((hashedPassword) => { return passwordCrypto.hash(this.data.password).then((hashedPassword) => {
this.data._hashed_password = hashedPassword; this.data._hashed_password = hashedPassword;
delete this.data.password; delete this.data.password;
}); });
@@ -701,15 +702,18 @@ RestWrite.prototype.objectId = function() {
return this.data.objectId || this.query.objectId; return this.data.objectId || this.query.objectId;
}; };
// Returns a string that's usable as an object id. // Returns a unique string that's usable as an object id.
// Probably unique. Good enough? Probably!
function newObjectId() { function newObjectId() {
var chars = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' + var chars = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'abcdefghijklmnopqrstuvwxyz' + 'abcdefghijklmnopqrstuvwxyz' +
'0123456789'); '0123456789');
var objectId = ''; var objectId = '';
for (var i = 0; i < 10; ++i) { var bytes = crypto.randomBytes(10);
objectId += chars[Math.floor(Math.random() * chars.length)]; for (var i = 0; i < bytes.length; ++i) {
// Note: there is a slight modulo bias, because chars length
// of 62 doesn't divide the number of all bytes (256) evenly.
// It is acceptable for our purposes.
objectId += chars[bytes.readUInt8(i) % chars.length];
} }
return objectId; return objectId;
} }

77
S3Adapter.js Normal file
View File

@@ -0,0 +1,77 @@
// S3Adapter
//
// Stores Parse files in AWS S3.
var AWS = require('aws-sdk');
var path = require('path');
var DEFAULT_REGION = "us-east-1";
var DEFAULT_BUCKET = "parse-files";
// Creates an S3 session.
// Providing AWS access and secret keys is mandatory
// Region and bucket will use sane defaults if omitted
function S3Adapter(accessKey, secretKey, options) {
options = options || {};
this.region = options.region || DEFAULT_REGION;
this.bucket = options.bucket || DEFAULT_BUCKET;
this.bucketPrefix = options.bucketPrefix || "";
this.directAccess = options.directAccess || false;
s3Options = {
accessKeyId: accessKey,
secretAccessKey: secretKey,
params: {Bucket: this.bucket}
};
AWS.config.region = this.region;
this.s3 = new AWS.S3(s3Options);
}
// For a given config object, filename, and data, store a file in S3
// Returns a promise containing the S3 object creation response
S3Adapter.prototype.create = function(config, filename, data) {
var params = {
Key: this.bucketPrefix + filename,
Body: data,
};
if (this.directAccess) {
params.ACL = "public-read"
}
return new Promise((resolve, reject) => {
this.s3.upload(params, (err, data) => {
if (err !== null) return reject(err);
resolve(data);
});
});
}
// Search for and return a file if found by filename
// Returns a promise that succeeds with the buffer result from S3
S3Adapter.prototype.get = function(config, filename) {
var params = {Key: this.bucketPrefix + filename};
return new Promise((resolve, reject) => {
this.s3.getObject(params, (err, data) => {
if (err !== null) return reject(err);
resolve(data.Body);
});
});
}
// Generates and returns the location of a file stored in S3 for the given request and
// filename
// The location is the direct S3 link if the option is set, otherwise we serve
// the file through parse-server
S3Adapter.prototype.location = function(config, req, filename) {
if (this.directAccess) {
return ('https://' + this.bucket + '.s3.amazonaws.com' + '/' +
this.bucketPrefix + filename);
}
return (req.protocol + '://' + req.get('host') +
path.dirname(req.originalUrl) + '/' + req.config.applicationId +
'/' + encodeURIComponent(filename));
}
module.exports = S3Adapter;

View File

@@ -10,31 +10,36 @@ var router = new PromiseRouter();
// Returns a promise that resolves to a {response} object. // Returns a promise that resolves to a {response} object.
function handleFind(req) { function handleFind(req) {
var body = Object.assign(req.body, req.query);
var options = {}; var options = {};
if (req.body.skip) { if (body.skip) {
options.skip = Number(req.body.skip); options.skip = Number(body.skip);
} }
if (req.body.limit) { if (body.limit) {
options.limit = Number(req.body.limit); options.limit = Number(body.limit);
} }
if (req.body.order) { if (body.order) {
options.order = String(req.body.order); options.order = String(body.order);
} }
if (req.body.count) { if (body.count) {
options.count = true; options.count = true;
} }
if (typeof req.body.keys == 'string') { if (typeof body.keys == 'string') {
options.keys = req.body.keys; options.keys = body.keys;
} }
if (req.body.include) { if (body.include) {
options.include = String(req.body.include); options.include = String(body.include);
} }
if (req.body.redirectClassNameForKey) { if (body.redirectClassNameForKey) {
options.redirectClassNameForKey = String(req.body.redirectClassNameForKey); options.redirectClassNameForKey = String(body.redirectClassNameForKey);
}
if(typeof body.where === 'string') {
body.where = JSON.parse(body.where);
} }
return rest.find(req.config, req.auth, return rest.find(req.config, req.auth,
req.params.className, req.body.where, options) req.params.className, body.where, options)
.then((response) => { .then((response) => {
return {response: response}; return {response: response};
}); });

View File

@@ -7,7 +7,6 @@ var bodyParser = require('body-parser'),
middlewares = require('./middlewares.js'), middlewares = require('./middlewares.js'),
mime = require('mime'), mime = require('mime'),
Parse = require('parse/node').Parse, Parse = require('parse/node').Parse,
path = require('path'),
rack = require('hat').rack(); rack = require('hat').rack();
var router = express.Router(); var router = express.Router();
@@ -44,10 +43,7 @@ var processCreate = function(req, res, next) {
FilesAdapter.getAdapter().create(req.config, filename, req.body) FilesAdapter.getAdapter().create(req.config, filename, req.body)
.then(() => { .then(() => {
res.status(201); res.status(201);
var location = (req.protocol + '://' + req.get('host') + var location = FilesAdapter.getAdapter().location(req.config, req, filename);
path.dirname(req.originalUrl) + '/' +
req.config.applicationId + '/' +
encodeURIComponent(filename));
res.set('Location', location); res.set('Location', location);
res.json({ url: location, name: filename }); res.json({ url: location, name: filename });
}).catch((error) => { }).catch((error) => {

View File

@@ -6,6 +6,7 @@ var batch = require('./batch'),
DatabaseAdapter = require('./DatabaseAdapter'), DatabaseAdapter = require('./DatabaseAdapter'),
express = require('express'), express = require('express'),
FilesAdapter = require('./FilesAdapter'), FilesAdapter = require('./FilesAdapter'),
S3Adapter = require('./S3Adapter'),
middlewares = require('./middlewares'), middlewares = require('./middlewares'),
multer = require('multer'), multer = require('multer'),
Parse = require('parse/node').Parse, Parse = require('parse/node').Parse,
@@ -47,7 +48,7 @@ function ParseServer(args) {
FilesAdapter.setAdapter(args.filesAdapter); FilesAdapter.setAdapter(args.filesAdapter);
} }
if (args.databaseURI) { if (args.databaseURI) {
DatabaseAdapter.setDatabaseURI(args.databaseURI); DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
} }
if (args.cloud) { if (args.cloud) {
addParseCloud(); addParseCloud();
@@ -150,6 +151,9 @@ function addParseCloud() {
options.uri = options.url; options.uri = options.url;
delete options.url; delete options.url;
} }
if (typeof options.body === 'object') {
options.body = JSON.stringify(options.body);
}
request(options, (error, response, body) => { request(options, (error, response, body) => {
if (error) { if (error) {
if (callbacks.error) { if (callbacks.error) {
@@ -176,6 +180,6 @@ function getClassName(parseClass) {
} }
module.exports = { module.exports = {
ParseServer: ParseServer ParseServer: ParseServer,
S3Adapter: S3Adapter
}; };

View File

@@ -1,6 +1,6 @@
{ {
"name": "parse-server", "name": "parse-server",
"version": "2.0.3", "version": "2.0.4",
"description": "An express module providing a Parse-compatible API server", "description": "An express module providing a Parse-compatible API server",
"main": "index.js", "main": "index.js",
"repository": { "repository": {
@@ -9,7 +9,8 @@
}, },
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"bcrypt": "~0.8", "aws-sdk": "~2.2.33",
"bcrypt-nodejs": "0.0.3",
"body-parser": "~1.12.4", "body-parser": "~1.12.4",
"deepcopy": "^0.5.0", "deepcopy": "^0.5.0",
"express": "~4.2.x", "express": "~4.2.x",

View File

@@ -1,11 +1,11 @@
// Tools for encrypting and decrypting passwords. // Tools for encrypting and decrypting passwords.
// Basically promise-friendly wrappers for bcrypt. // Basically promise-friendly wrappers for bcrypt.
var bcrypt = require('bcrypt'); var bcrypt = require('bcrypt-nodejs');
// Returns a promise for a hashed password string. // Returns a promise for a hashed password string.
function hash(password) { function hash(password) {
return new Promise(function(fulfill, reject) { return new Promise(function(fulfill, reject) {
bcrypt.hash(password, 8, function(err, hashedPassword) { bcrypt.hash(password, null, null, function(err, hashedPassword) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {

View File

@@ -6,7 +6,7 @@
// Tests that involve sending password reset emails. // Tests that involve sending password reset emails.
var request = require('request'); var request = require('request');
var crypto = require('../crypto'); var passwordCrypto = require('../password');
describe('Parse.User testing', () => { describe('Parse.User testing', () => {
it("user sign up class method", (done) => { it("user sign up class method", (done) => {
@@ -1560,7 +1560,7 @@ describe('Parse.User testing', () => {
it('password format matches hosted parse', (done) => { it('password format matches hosted parse', (done) => {
var hashed = '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie'; var hashed = '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie';
crypto.compare('test', hashed) passwordCrypto.compare('test', hashed)
.then((pass) => { .then((pass) => {
expect(pass).toBe(true); expect(pass).toBe(true);
done(); done();
@@ -1574,7 +1574,7 @@ describe('Parse.User testing', () => {
var sessionToken = null; var sessionToken = null;
Parse.Promise.as().then(function() { Parse.Promise.as().then(function() {
return Parse.User.signUp("fosco", "parse"); return Parse.User.signUp("fosco", "parse");
}).then(function(newUser) { }).then(function(newUser) {
equal(Parse.User.current(), newUser); equal(Parse.User.current(), newUser);
sessionToken = newUser.getSessionToken(); sessionToken = newUser.getSessionToken();

View File

@@ -2,16 +2,18 @@
var transform = require('../transform'); var transform = require('../transform');
var dummyConfig = { var dummySchema = {
schema: {
data: {}, data: {},
getExpectedType: function(className, key) { getExpectedType: function(className, key) {
if (key == 'userPointer') { if (key == 'userPointer') {
return '*_User'; return '*_User';
} else if (key == 'picture') {
return 'file';
} else if (key == 'location') {
return 'geopoint';
} }
return; return;
} }
}
}; };
@@ -19,7 +21,7 @@ describe('transformCreate', () => {
it('a basic number', (done) => { it('a basic number', (done) => {
var input = {five: 5}; var input = {five: 5};
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
jequal(input, output); jequal(input, output);
done(); done();
}); });
@@ -29,7 +31,7 @@ describe('transformCreate', () => {
createdAt: "2015-10-06T21:24:50.332Z", createdAt: "2015-10-06T21:24:50.332Z",
updatedAt: "2015-10-06T21:24:50.332Z" updatedAt: "2015-10-06T21:24:50.332Z"
}; };
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
expect(output._created_at instanceof Date).toBe(true); expect(output._created_at instanceof Date).toBe(true);
expect(output._updated_at instanceof Date).toBe(true); expect(output._updated_at instanceof Date).toBe(true);
done(); done();
@@ -41,21 +43,21 @@ describe('transformCreate', () => {
objectId: 'myId', objectId: 'myId',
className: 'Blah', className: 'Blah',
}; };
var out = transform.transformCreate(dummyConfig, null, {pointers: [pointer]}); var out = transform.transformCreate(dummySchema, null, {pointers: [pointer]});
jequal([pointer], out.pointers); jequal([pointer], out.pointers);
done(); done();
}); });
it('a delete op', (done) => { it('a delete op', (done) => {
var input = {deleteMe: {__op: 'Delete'}}; var input = {deleteMe: {__op: 'Delete'}};
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
jequal(output, {}); jequal(output, {});
done(); done();
}); });
it('basic ACL', (done) => { it('basic ACL', (done) => {
var input = {ACL: {'0123': {'read': true, 'write': true}}}; var input = {ACL: {'0123': {'read': true, 'write': true}}};
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
// This just checks that it doesn't crash, but it should check format. // This just checks that it doesn't crash, but it should check format.
done(); done();
}); });
@@ -63,7 +65,7 @@ describe('transformCreate', () => {
describe('transformWhere', () => { describe('transformWhere', () => {
it('objectId', (done) => { it('objectId', (done) => {
var out = transform.transformWhere(dummyConfig, null, {objectId: 'foo'}); var out = transform.transformWhere(dummySchema, null, {objectId: 'foo'});
expect(out._id).toEqual('foo'); expect(out._id).toEqual('foo');
done(); done();
}); });
@@ -72,7 +74,7 @@ describe('transformWhere', () => {
var input = { var input = {
objectId: {'$in': ['one', 'two', 'three']}, objectId: {'$in': ['one', 'two', 'three']},
}; };
var output = transform.transformWhere(dummyConfig, null, input); var output = transform.transformWhere(dummySchema, null, input);
jequal(input.objectId, output._id); jequal(input.objectId, output._id);
done(); done();
}); });
@@ -81,17 +83,53 @@ describe('transformWhere', () => {
describe('untransformObject', () => { describe('untransformObject', () => {
it('built-in timestamps', (done) => { it('built-in timestamps', (done) => {
var input = {createdAt: new Date(), updatedAt: new Date()}; var input = {createdAt: new Date(), updatedAt: new Date()};
var output = transform.untransformObject(dummyConfig, null, input); var output = transform.untransformObject(dummySchema, null, input);
expect(typeof output.createdAt).toEqual('string'); expect(typeof output.createdAt).toEqual('string');
expect(typeof output.updatedAt).toEqual('string'); expect(typeof output.updatedAt).toEqual('string');
done(); done();
}); });
it('pointer', (done) => {
var input = {_p_userPointer: '_User$123'};
var output = transform.untransformObject(dummySchema, null, input);
expect(typeof output.userPointer).toEqual('object');
expect(output.userPointer).toEqual(
{__type: 'Pointer', className: '_User', objectId: '123'}
);
done();
});
it('null pointer', (done) => {
var input = {_p_userPointer: null};
var output = transform.untransformObject(dummySchema, null, input);
expect(output.userPointer).toBeUndefined();
done();
});
it('file', (done) => {
var input = {picture: 'pic.jpg'};
var output = transform.untransformObject(dummySchema, null, input);
expect(typeof output.picture).toEqual('object');
expect(output.picture).toEqual({__type: 'File', name: 'pic.jpg'});
done();
});
it('geopoint', (done) => {
var input = {location: [180, -180]};
var output = transform.untransformObject(dummySchema, null, input);
expect(typeof output.location).toEqual('object');
expect(output.location).toEqual(
{__type: 'GeoPoint', longitude: 180, latitude: -180}
);
done();
});
}); });
describe('transformKey', () => { describe('transformKey', () => {
it('throws out _password', (done) => { it('throws out _password', (done) => {
try { try {
transform.transformKey(dummyConfig, '_User', '_password'); transform.transformKey(dummySchema, '_User', '_password');
fail('should have thrown'); fail('should have thrown');
} catch (e) { } catch (e) {
done(); done();
@@ -105,7 +143,7 @@ describe('transform schema key changes', () => {
var input = { var input = {
somePointer: {__type: 'Pointer', className: 'Micro', objectId: 'oft'} somePointer: {__type: 'Pointer', className: 'Micro', objectId: 'oft'}
}; };
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
expect(typeof output._p_somePointer).toEqual('string'); expect(typeof output._p_somePointer).toEqual('string');
expect(output._p_somePointer).toEqual('Micro$oft'); expect(output._p_somePointer).toEqual('Micro$oft');
done(); done();
@@ -115,7 +153,7 @@ describe('transform schema key changes', () => {
var input = { var input = {
userPointer: {__type: 'Pointer', className: '_User', objectId: 'qwerty'} userPointer: {__type: 'Pointer', className: '_User', objectId: 'qwerty'}
}; };
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
expect(typeof output._p_userPointer).toEqual('string'); expect(typeof output._p_userPointer).toEqual('string');
expect(output._p_userPointer).toEqual('_User$qwerty'); expect(output._p_userPointer).toEqual('_User$qwerty');
done(); done();
@@ -128,7 +166,7 @@ describe('transform schema key changes', () => {
"Kevin": { "write": true } "Kevin": { "write": true }
} }
}; };
var output = transform.transformCreate(dummyConfig, null, input); var output = transform.transformCreate(dummySchema, null, input);
expect(typeof output._rperm).toEqual('object'); expect(typeof output._rperm).toEqual('object');
expect(typeof output._wperm).toEqual('object'); expect(typeof output._wperm).toEqual('object');
expect(output.ACL).toBeUndefined(); expect(output.ACL).toBeUndefined();
@@ -142,7 +180,7 @@ describe('transform schema key changes', () => {
_rperm: ["*"], _rperm: ["*"],
_wperm: ["Kevin"] _wperm: ["Kevin"]
}; };
var output = transform.untransformObject(dummyConfig, null, input); var output = transform.untransformObject(dummySchema, null, input);
expect(typeof output.ACL).toEqual('object'); expect(typeof output.ACL).toEqual('object');
expect(output._rperm).toBeUndefined(); expect(output._rperm).toBeUndefined();
expect(output._wperm).toBeUndefined(); expect(output._wperm).toBeUndefined();

View File

@@ -676,6 +676,9 @@ function untransformObject(schema, className, mongoObject) {
console.log('Found a pointer in a non-pointer column, dropping it.', className, key); console.log('Found a pointer in a non-pointer column, dropping it.', className, key);
break; break;
} }
if (mongoObject[key] === null) {
break;
}
var objData = mongoObject[key].split('$'); var objData = mongoObject[key].split('$');
var newClass = (expected ? expected.substring(1) : objData[0]); var newClass = (expected ? expected.substring(1) : objData[0]);
if (objData[0] !== newClass) { if (objData[0] !== newClass) {
@@ -689,9 +692,11 @@ function untransformObject(schema, className, mongoObject) {
break; break;
} else if (key[0] == '_' && key != '__type') { } else if (key[0] == '_' && key != '__type') {
throw ('bad key in untransform: ' + key); throw ('bad key in untransform: ' + key);
//} else if (mongoObject[key] === null) {
//break;
} else { } else {
var expected = schema.getExpectedType(className, key); var expected = schema.getExpectedType(className, key);
if (expected == 'file') { if (expected == 'file' && mongoObject[key]) {
restObject[key] = { restObject[key] = {
__type: 'File', __type: 'File',
name: mongoObject[key] name: mongoObject[key]

View File

@@ -5,7 +5,7 @@ var Parse = require('parse/node').Parse;
var rack = require('hat').rack(); var rack = require('hat').rack();
var Auth = require('./Auth'); var Auth = require('./Auth');
var crypto = require('./crypto'); var passwordCrypto = require('./password');
var facebook = require('./facebook'); var facebook = require('./facebook');
var PromiseRouter = require('./PromiseRouter'); var PromiseRouter = require('./PromiseRouter');
var rest = require('./rest'); var rest = require('./rest');
@@ -45,7 +45,7 @@ function handleLogIn(req) {
'Invalid username/password.'); 'Invalid username/password.');
} }
user = results[0]; user = results[0];
return crypto.compare(req.body.password, user.password); return passwordCrypto.compare(req.body.password, user.password);
}).then((correct) => { }).then((correct) => {
if (!correct) { if (!correct) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND,
@@ -70,9 +70,13 @@ function handleLogIn(req) {
'authProvider': 'password' 'authProvider': 'password'
}, },
restricted: false, restricted: false,
expiresAt: Parse._encode(expiresAt).iso, expiresAt: Parse._encode(expiresAt)
installationId: req.info.installationId
}; };
if (req.info.installationId) {
sessionData.installationId = req.info.installationId
}
var create = new RestWrite(req.config, Auth.master(req.config), var create = new RestWrite(req.config, Auth.master(req.config),
'_Session', null, sessionData); '_Session', null, sessionData);
return create.execute(); return create.execute();