mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Replace Underscore methods with native ECMAScript.
This removes `underscore` entirely from `allow-deny`.
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
/// Remote methods and access control.
|
||||
///
|
||||
|
||||
const hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
// Restrict default mutators on collection. allow() and deny() take the
|
||||
// same options:
|
||||
//
|
||||
@@ -108,7 +110,7 @@ CollectionPrototype._defineMutationMethods = function(options) {
|
||||
if (self._connection && (self._connection === Meteor.server || Meteor.isClient)) {
|
||||
const m = {};
|
||||
|
||||
_.each(['insert', 'update', 'remove'], function (method) {
|
||||
['insert', 'update', 'remove'].forEach((method) => {
|
||||
const methodName = self._prefix + method;
|
||||
|
||||
if (options.useExisting) {
|
||||
@@ -122,7 +124,7 @@ CollectionPrototype._defineMutationMethods = function(options) {
|
||||
m[methodName] = function (/* ... */) {
|
||||
// All the methods do their own validation, instead of using check().
|
||||
check(arguments, [Match.Any]);
|
||||
const args = _.toArray(arguments);
|
||||
const args = Array.from(arguments);
|
||||
try {
|
||||
// For an insert, if the client didn't specify an _id, generate one
|
||||
// now; because this uses DDP.randomStream, it will be consistent with
|
||||
@@ -136,7 +138,7 @@ CollectionPrototype._defineMutationMethods = function(options) {
|
||||
// between arbitrary client-specified _id fields and merely
|
||||
// client-controlled-via-randomSeed fields.
|
||||
let generatedId = null;
|
||||
if (method === "insert" && !_.has(args[0], '_id')) {
|
||||
if (method === "insert" && !hasOwn.call(args[0], '_id')) {
|
||||
generatedId = self._makeNewID();
|
||||
}
|
||||
|
||||
@@ -208,7 +210,9 @@ CollectionPrototype._updateFetch = function (fields) {
|
||||
|
||||
if (!self._validators.fetchAllFields) {
|
||||
if (fields) {
|
||||
self._validators.fetch = _.union(self._validators.fetch, fields);
|
||||
self._validators.fetch =
|
||||
// union
|
||||
Array.from(new Set([...self._validators.fetch, ...fields]));
|
||||
} else {
|
||||
self._validators.fetchAllFields = true;
|
||||
// clear fetch just to make sure we don't accidentally read it
|
||||
@@ -230,13 +234,13 @@ CollectionPrototype._validatedInsert = function (userId, doc,
|
||||
|
||||
// call user validators.
|
||||
// Any deny returns true means denied.
|
||||
if (_.any(self._validators.insert.deny, function(validator) {
|
||||
if (self._validators.insert.deny.some((validator) => {
|
||||
return validator(userId, docToValidate(validator, doc, generatedId));
|
||||
})) {
|
||||
throw new Meteor.Error(403, "Access denied");
|
||||
}
|
||||
// Any allow returns true means proceed. Throw error if they all fail.
|
||||
if (_.all(self._validators.insert.allow, function(validator) {
|
||||
if (self._validators.insert.allow.every((validator) => {
|
||||
return !validator(userId, docToValidate(validator, doc, generatedId));
|
||||
})) {
|
||||
throw new Meteor.Error(403, "Access denied");
|
||||
@@ -260,7 +264,7 @@ CollectionPrototype._validatedUpdate = function(
|
||||
|
||||
check(mutator, Object);
|
||||
|
||||
options = _.clone(options) || {};
|
||||
options = Object.assign(Object.create(null), options);
|
||||
|
||||
if (!LocalCollection._selectorIsIdPerhapsAsObject(selector))
|
||||
throw new Error("validated update should be of a single ID");
|
||||
@@ -275,26 +279,29 @@ CollectionPrototype._validatedUpdate = function(
|
||||
" update documents, not replace them. Use a Mongo update operator, such " +
|
||||
"as '$set'.";
|
||||
|
||||
const mutatorKeys = Object.keys(mutator);
|
||||
|
||||
// compute modified fields
|
||||
const fields = [];
|
||||
if (_.isEmpty(mutator)) {
|
||||
if (mutatorKeys.length === 0) {
|
||||
throw new Meteor.Error(403, noReplaceError);
|
||||
}
|
||||
_.each(mutator, function (params, op) {
|
||||
mutatorKeys.forEach((op) => {
|
||||
const params = mutator[op];
|
||||
if (op.charAt(0) !== '$') {
|
||||
throw new Meteor.Error(403, noReplaceError);
|
||||
} else if (!_.has(ALLOWED_UPDATE_OPERATIONS, op)) {
|
||||
} else if (!hasOwn.call(ALLOWED_UPDATE_OPERATIONS, op)) {
|
||||
throw new Meteor.Error(
|
||||
403, "Access denied. Operator " + op + " not allowed in a restricted collection.");
|
||||
} else {
|
||||
_.each(_.keys(params), function (field) {
|
||||
Object.keys(params).forEach((field) => {
|
||||
// treat dotted fields as if they are replacing their
|
||||
// top-level part
|
||||
if (field.indexOf('.') !== -1)
|
||||
field = field.substring(0, field.indexOf('.'));
|
||||
|
||||
// record the field we are trying to change
|
||||
if (!_.contains(fields, field))
|
||||
if (!fields.includes(field))
|
||||
fields.push(field);
|
||||
});
|
||||
}
|
||||
@@ -303,7 +310,7 @@ CollectionPrototype._validatedUpdate = function(
|
||||
const findOptions = {transform: null};
|
||||
if (!self._validators.fetchAllFields) {
|
||||
findOptions.fields = {};
|
||||
_.each(self._validators.fetch, function(fieldName) {
|
||||
self._validators.fetch.forEach((fieldName) => {
|
||||
findOptions.fields[fieldName] = 1;
|
||||
});
|
||||
}
|
||||
@@ -314,7 +321,7 @@ CollectionPrototype._validatedUpdate = function(
|
||||
|
||||
// call user validators.
|
||||
// Any deny returns true means denied.
|
||||
if (_.any(self._validators.update.deny, function(validator) {
|
||||
if (self._validators.update.deny.some((validator) => {
|
||||
const factoriedDoc = transformDoc(validator, doc);
|
||||
return validator(userId,
|
||||
factoriedDoc,
|
||||
@@ -324,7 +331,7 @@ CollectionPrototype._validatedUpdate = function(
|
||||
throw new Meteor.Error(403, "Access denied");
|
||||
}
|
||||
// Any allow returns true means proceed. Throw error if they all fail.
|
||||
if (_.all(self._validators.update.allow, function(validator) {
|
||||
if (self._validators.update.allow.every((validator) => {
|
||||
const factoriedDoc = transformDoc(validator, doc);
|
||||
return !validator(userId,
|
||||
factoriedDoc,
|
||||
@@ -364,7 +371,7 @@ CollectionPrototype._validatedRemove = function(userId, selector) {
|
||||
const findOptions = {transform: null};
|
||||
if (!self._validators.fetchAllFields) {
|
||||
findOptions.fields = {};
|
||||
_.each(self._validators.fetch, function(fieldName) {
|
||||
self._validators.fetch.forEach((fieldName) => {
|
||||
findOptions.fields[fieldName] = 1;
|
||||
});
|
||||
}
|
||||
@@ -375,13 +382,13 @@ CollectionPrototype._validatedRemove = function(userId, selector) {
|
||||
|
||||
// call user validators.
|
||||
// Any deny returns true means denied.
|
||||
if (_.any(self._validators.remove.deny, function(validator) {
|
||||
if (self._validators.remove.deny.some((validator) => {
|
||||
return validator(userId, transformDoc(validator, doc));
|
||||
})) {
|
||||
throw new Meteor.Error(403, "Access denied");
|
||||
}
|
||||
// Any allow returns true means proceed. Throw error if they all fail.
|
||||
if (_.all(self._validators.remove.allow, function(validator) {
|
||||
if (self._validators.remove.allow.every((validator) => {
|
||||
return !validator(userId, transformDoc(validator, doc));
|
||||
})) {
|
||||
throw new Meteor.Error(403, "Access denied");
|
||||
@@ -451,15 +458,15 @@ function docToValidate(validator, doc, generatedId) {
|
||||
function addValidator(collection, allowOrDeny, options) {
|
||||
// validate keys
|
||||
const VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform'];
|
||||
_.each(_.keys(options), function (key) {
|
||||
if (!_.contains(VALID_KEYS, key))
|
||||
Object.keys(options).forEach((key) => {
|
||||
if (!VALID_KEYS.includes(key))
|
||||
throw new Error(allowOrDeny + ": Invalid key: " + key);
|
||||
});
|
||||
|
||||
collection._restricted = true;
|
||||
|
||||
_.each(['insert', 'update', 'remove'], function (name) {
|
||||
if (options.hasOwnProperty(name)) {
|
||||
['insert', 'update', 'remove'].forEach((name) => {
|
||||
if (hasOwn.call(options, name)) {
|
||||
if (!(options[name] instanceof Function)) {
|
||||
throw new Error(allowOrDeny + ": Value for `" + name + "` must be a function");
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ Package.describe({
|
||||
Package.onUse(function(api) {
|
||||
api.use([
|
||||
'ecmascript',
|
||||
'underscore',
|
||||
'minimongo', // Just for LocalCollection.wrapTransform :[
|
||||
'check',
|
||||
'ejson',
|
||||
|
||||
Reference in New Issue
Block a user