Merge remote-tracking branch 'ParsePlatform/master' into user-roles

This commit is contained in:
Francis Lessard
2016-02-18 14:00:11 -05:00
11 changed files with 231 additions and 87 deletions

View File

@@ -306,7 +306,8 @@ ExportAdapter.prototype.destroy = function(className, query, options = {}) {
return coll.remove(mongoWhere);
}).then((resp) => {
if (resp.result.n === 0) {
//Check _Session to avoid changing password failed without any session.
if (resp.result.n === 0 && className !== "_Session") {
return Promise.reject(
new Parse.Error(Parse.Error.OBJECT_NOT_FOUND,
'Object not found.'));

View File

@@ -54,10 +54,17 @@ export class ClassesRouter {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
}
if(req.params.className === "_User"){
if (req.params.className === "_User") {
delete response.results[0].sessionToken;
}
const user = response.results[0];
if (req.auth.user && user.objectId == req.auth.user.id) {
// Force the session token
response.results[0].sessionToken = req.info.sessionToken;
}
}
return { response: response.results[0] };
});
}

View File

@@ -521,7 +521,7 @@ Schema.prototype.deleteField = function(fieldName, className, database, prefix)
});
}
if (schema.data[className][fieldName].startsWith('relation')) {
if (schema.data[className][fieldName].startsWith('relation<')) {
//For relations, drop the _Join table
return database.dropCollection(prefix + '_Join:' + fieldName + ':' + className)
//Save the _SCHEMA object
@@ -714,6 +714,7 @@ function getObjectType(obj) {
module.exports = {
load: load,
classNameIsValid: classNameIsValid,
invalidClassNameMessage: invalidClassNameMessage,
mongoSchemaFromFieldsAndClassName: mongoSchemaFromFieldsAndClassName,
schemaAPITypeToMongoFieldType: schemaAPITypeToMongoFieldType,
buildMergedSchemaObject: buildMergedSchemaObject,

View File

@@ -1,58 +0,0 @@
// Helper functions for accessing the Facebook Graph API.
var https = require('https');
var Parse = require('parse/node').Parse;
// Returns a promise that fulfills iff this user id is valid.
function validateAuthData(authData) {
return graphRequest('me?fields=id&access_token=' + authData.access_token)
.then((data) => {
if (data && data.id == authData.id) {
return;
}
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook auth is invalid for this user.');
});
}
// Returns a promise that fulfills iff this app id is valid.
function validateAppId(appIds, authData) {
var access_token = authData.access_token;
if (!appIds.length) {
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook auth is not configured.');
}
return graphRequest('app?access_token=' + access_token)
.then((data) => {
if (data && appIds.indexOf(data.id) != -1) {
return;
}
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'Facebook auth is invalid for this user.');
});
}
// A promisey wrapper for FB graph requests.
function graphRequest(path) {
return new Promise(function(resolve, reject) {
https.get('https://graph.facebook.com/v2.5/' + path, function(res) {
var data = '';
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
data = JSON.parse(data);
resolve(data);
});
}).on('error', function(e) {
reject('Failed to validate this access token with Facebook.');
});
});
}
module.exports = {
validateAppId: validateAppId,
validateAuthData: validateAuthData
};

View File

@@ -10,10 +10,15 @@ var router = new PromiseRouter();
function handleCloudFunction(req) {
if (Parse.Cloud.Functions[req.params.functionName]) {
const params = Object.assign({}, req.body, req.query);
var request = {
params: Object.assign({}, req.body, req.query),
master: req.auth && req.auth.isMaster,
user: req.auth && req.auth.user,
installationId: req.info.installationId
};
if (Parse.Cloud.Validators[req.params.functionName]) {
var result = Parse.Cloud.Validators[req.params.functionName](params);
var result = Parse.Cloud.Validators[req.params.functionName](request);
if (!result) {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Validation failed.');
}
@@ -21,12 +26,6 @@ function handleCloudFunction(req) {
return new Promise(function (resolve, reject) {
var response = createResponseObject(resolve, reject);
var request = {
params: params,
master: req.auth && req.auth.isMaster,
user: req.auth && req.auth.user,
installationId: req.info.installationId
};
Parse.Cloud.Functions[req.params.functionName](request, response);
});
} else {

View File

@@ -16,7 +16,8 @@ function validateAuthData(authData) {
}
// Returns a promise that fulfills iff this app id is valid.
function validateAppId(appIds, access_token) {
function validateAppId(appIds, authData) {
var access_token = authData.access_token;
if (!appIds.length) {
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,

View File

@@ -183,10 +183,95 @@ function modifySchema(req) {
});
}
// A helper function that removes all join tables for a schema. Returns a promise.
var removeJoinTables = (database, prefix, mongoSchema) => {
return Promise.all(Object.keys(mongoSchema)
.filter(field => mongoSchema[field].startsWith('relation<'))
.map(field => {
var joinCollectionName = prefix + '_Join:' + field + ':' + mongoSchema._id;
return new Promise((resolve, reject) => {
database.dropCollection(joinCollectionName, (err, results) => {
if (err) {
reject(err);
} else {
resolve();
}
})
});
})
);
};
function deleteSchema(req) {
if (!req.auth.isMaster) {
return masterKeyRequiredResponse();
}
if (!Schema.classNameIsValid(req.params.className)) {
return Promise.resolve({
status: 400,
response: {
code: Parse.Error.INVALID_CLASS_NAME,
error: Schema.invalidClassNameMessage(req.params.className),
}
});
}
return req.config.database.collection(req.params.className)
.then(coll => new Promise((resolve, reject) => {
coll.count((err, count) => {
if (err) {
reject(err);
} else if (count > 0) {
resolve({
status: 400,
response: {
code: 255,
error: 'class ' + req.params.className + ' not empty, contains ' + count + ' objects, cannot drop schema',
}
});
} else {
coll.drop((err, reply) => {
if (err) {
reject(err);
} else {
// We've dropped the collection now, so delete the item from _SCHEMA
// and clear the _Join collections
req.config.database.collection('_SCHEMA')
.then(coll => new Promise((resolve, reject) => {
coll.findAndRemove({ _id: req.params.className }, [], (err, doc) => {
if (err) {
reject(err);
} else if (doc.value === null) {
//tried to delete non-existant class
resolve({ response: {}});
} else {
removeJoinTables(req.config.database.db, req.config.database.collectionPrefix, doc.value)
.then(resolve, reject);
}
});
}))
.then(resolve.bind(undefined, {response: {}}), reject);
}
});
}
});
}))
.catch(error => {
if (error.message == 'ns not found') {
// If they try to delete a non-existant class, thats fine, just let them.
return Promise.resolve({ response: {} });
} else {
return Promise.reject(error);
}
});
}
router.route('GET', '/schemas', getAllSchemas);
router.route('GET', '/schemas/:className', getOneSchema);
router.route('POST', '/schemas', createSchema);
router.route('POST', '/schemas/:className', createSchema);
router.route('PUT', '/schemas/:className', modifySchema);
router.route('DELETE', '/schemas/:className', deleteSchema);
module.exports = router;