Cleanup update (#1590)
* destructuring in DB controller * deleteObject in db adapter * Turns out we can't have delete by object ID because of ACLs... * Fix tests * destructure acl * Don't reject with object
This commit is contained in:
@@ -87,10 +87,10 @@ DatabaseController.prototype.redirectClassNameForKey = function(className, key)
|
||||
// Returns a promise that resolves to the new schema.
|
||||
// This does not update this.schema, because in a situation like a
|
||||
// batch request, that could confuse other users of the schema.
|
||||
DatabaseController.prototype.validateObject = function(className, object, query, options) {
|
||||
DatabaseController.prototype.validateObject = function(className, object, query, { acl }) {
|
||||
let schema;
|
||||
let isMaster = !('acl' in options);
|
||||
var aclGroup = options.acl || [];
|
||||
let isMaster = acl === undefined;
|
||||
var aclGroup = acl || [];
|
||||
return this.loadSchema().then(s => {
|
||||
schema = s;
|
||||
if (isMaster) {
|
||||
@@ -131,14 +131,18 @@ DatabaseController.prototype.untransformObject = function(
|
||||
// acl: a list of strings. If the object to be updated has an ACL,
|
||||
// one of the provided strings must provide the caller with
|
||||
// write permissions.
|
||||
DatabaseController.prototype.update = function(className, query, update, options = {}) {
|
||||
DatabaseController.prototype.update = function(className, query, update, {
|
||||
acl,
|
||||
many,
|
||||
upsert,
|
||||
} = {}) {
|
||||
|
||||
const originalUpdate = update;
|
||||
// Make a copy of the object, so we don't mutate the incoming data.
|
||||
update = deepcopy(update);
|
||||
|
||||
var isMaster = !('acl' in options);
|
||||
var aclGroup = options.acl || [];
|
||||
var isMaster = acl === undefined;
|
||||
var aclGroup = acl || [];
|
||||
var mongoUpdate, schema;
|
||||
return this.loadSchema()
|
||||
.then(s => {
|
||||
@@ -152,19 +156,19 @@ DatabaseController.prototype.update = function(className, query, update, options
|
||||
.then(() => this.adapter.adaptiveCollection(className))
|
||||
.then(collection => {
|
||||
if (!isMaster) {
|
||||
query = this.addPointerPermissions(schema, className, 'update', query, aclGroup);
|
||||
query = this.addPointerPermissions(schema, className, 'update', query, aclGroup);
|
||||
}
|
||||
if (!query) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
var mongoWhere = this.transform.transformWhere(schema, className, query, {validate: !this.skipValidation});
|
||||
if (options.acl) {
|
||||
mongoWhere = this.transform.addWriteACL(mongoWhere, options.acl);
|
||||
if (acl) {
|
||||
mongoWhere = this.transform.addWriteACL(mongoWhere, acl);
|
||||
}
|
||||
mongoUpdate = this.transform.transformUpdate(schema, className, update, {validate: !this.skipValidation});
|
||||
if (options.many) {
|
||||
if (many) {
|
||||
return collection.updateMany(mongoWhere, mongoUpdate);
|
||||
}else if (options.upsert) {
|
||||
} else if (upsert) {
|
||||
return collection.upsertOne(mongoWhere, mongoUpdate);
|
||||
} else {
|
||||
return collection.findOneAndUpdate(mongoWhere, mongoUpdate);
|
||||
@@ -203,9 +207,7 @@ function sanitizeDatabaseResult(originalObject, result) {
|
||||
// Returns a promise that resolves successfully when these are
|
||||
// processed.
|
||||
// This mutates update.
|
||||
DatabaseController.prototype.handleRelationUpdates = function(className,
|
||||
objectId,
|
||||
update) {
|
||||
DatabaseController.prototype.handleRelationUpdates = function(className, objectId, update) {
|
||||
var pending = [];
|
||||
var deleteMe = [];
|
||||
objectId = update.objectId || objectId;
|
||||
@@ -282,51 +284,42 @@ DatabaseController.prototype.removeRelation = function(key, fromClassName, fromI
|
||||
// acl: a list of strings. If the object to be updated has an ACL,
|
||||
// one of the provided strings must provide the caller with
|
||||
// write permissions.
|
||||
DatabaseController.prototype.destroy = function(className, query, options = {}) {
|
||||
var isMaster = !('acl' in options);
|
||||
var aclGroup = options.acl || [];
|
||||
DatabaseController.prototype.destroy = function(className, query, { acl } = {}) {
|
||||
const isMaster = acl === undefined;
|
||||
const aclGroup = acl || [];
|
||||
|
||||
var schema;
|
||||
return this.loadSchema()
|
||||
.then(s => {
|
||||
schema = s;
|
||||
.then(schemaController => {
|
||||
return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'delete'))
|
||||
.then(() => {
|
||||
if (!isMaster) {
|
||||
return schema.validatePermission(className, aclGroup, 'delete');
|
||||
}
|
||||
return Promise.resolve();
|
||||
})
|
||||
.then(() => this.adapter.adaptiveCollection(className))
|
||||
.then(collection => {
|
||||
if (!isMaster) {
|
||||
query = this.addPointerPermissions(schema, className, 'delete', query, aclGroup);
|
||||
query = this.addPointerPermissions(schemaController, className, 'delete', query, aclGroup);
|
||||
if (!query) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
}
|
||||
}
|
||||
let mongoWhere = this.transform.transformWhere(schema, className, query, {validate: !this.skipValidation});
|
||||
if (options.acl) {
|
||||
mongoWhere = this.transform.addWriteACL(mongoWhere, options.acl);
|
||||
}
|
||||
return collection.deleteMany(mongoWhere);
|
||||
})
|
||||
.then(resp => {
|
||||
//Check _Session to avoid changing password failed without any session.
|
||||
// TODO: @nlutsenko Stop relying on `result.n`
|
||||
if (resp.result.n === 0 && className !== "_Session") {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
}
|
||||
// delete by query
|
||||
return this.adapter.deleteObjectsByQuery(className, query, acl, schemaController, !this.skipValidation)
|
||||
.catch(error => {
|
||||
// When deleting sessions while changing passwords, don't throw an error if they don't have any sessions.
|
||||
if (className === "_Session" && error.code === Parse.Error.OBJECT_NOT_FOUND) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Inserts an object into the database.
|
||||
// Returns a promise that resolves successfully iff the object saved.
|
||||
DatabaseController.prototype.create = function(className, object, options = {}) {
|
||||
DatabaseController.prototype.create = function(className, object, { acl } = {}) {
|
||||
// Make a copy of the object, so we don't mutate the incoming data.
|
||||
let originalObject = object;
|
||||
object = deepcopy(object);
|
||||
|
||||
var isMaster = !('acl' in options);
|
||||
var aclGroup = options.acl || [];
|
||||
var isMaster = acl === undefined;
|
||||
var aclGroup = acl || [];
|
||||
|
||||
return this.validateClassName(className)
|
||||
.then(() => this.loadSchema())
|
||||
@@ -570,27 +563,33 @@ DatabaseController.prototype.addNotInObjectIdsIds = function(ids = null, query)
|
||||
// TODO: make userIds not needed here. The db adapter shouldn't know
|
||||
// anything about users, ideally. Then, improve the format of the ACL
|
||||
// arg to work like the others.
|
||||
DatabaseController.prototype.find = function(className, query, options = {}) {
|
||||
DatabaseController.prototype.find = function(className, query, {
|
||||
skip,
|
||||
limit,
|
||||
acl,
|
||||
sort,
|
||||
count,
|
||||
} = {}) {
|
||||
let mongoOptions = {};
|
||||
if (options.skip) {
|
||||
mongoOptions.skip = options.skip;
|
||||
if (skip) {
|
||||
mongoOptions.skip = skip;
|
||||
}
|
||||
if (options.limit) {
|
||||
mongoOptions.limit = options.limit;
|
||||
if (limit) {
|
||||
mongoOptions.limit = limit;
|
||||
}
|
||||
let isMaster = !('acl' in options);
|
||||
let aclGroup = options.acl || [];
|
||||
let isMaster = acl === undefined;
|
||||
let aclGroup = acl || [];
|
||||
let schema = null;
|
||||
let op = typeof query.objectId == 'string' && Object.keys(query).length === 1 ?
|
||||
'get' :
|
||||
'find';
|
||||
return this.loadSchema().then(s => {
|
||||
schema = s;
|
||||
if (options.sort) {
|
||||
if (sort) {
|
||||
mongoOptions.sort = {};
|
||||
for (let key in options.sort) {
|
||||
for (let key in sort) {
|
||||
let mongoKey = this.transform.transformKey(schema, className, key);
|
||||
mongoOptions.sort[mongoKey] = options.sort[key];
|
||||
mongoOptions.sort[mongoKey] = sort[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,7 +603,7 @@ DatabaseController.prototype.find = function(className, query, options = {}) {
|
||||
.then(() => this.adapter.adaptiveCollection(className))
|
||||
.then(collection => {
|
||||
if (!isMaster) {
|
||||
query = this.addPointerPermissions(schema, className, op, query, aclGroup);
|
||||
query = this.addPointerPermissions(schema, className, op, query, aclGroup);
|
||||
}
|
||||
if (!query) {
|
||||
if (op == 'get') {
|
||||
@@ -618,7 +617,7 @@ DatabaseController.prototype.find = function(className, query, options = {}) {
|
||||
if (!isMaster) {
|
||||
mongoWhere = this.transform.addReadACL(mongoWhere, aclGroup);
|
||||
}
|
||||
if (options.count) {
|
||||
if (count) {
|
||||
delete mongoOptions.limit;
|
||||
return collection.count(mongoWhere, mongoOptions);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user