Managing document field permissions in a Meteor application: Best practices for restricting which fields can be inserted or updated

I am currently using Meteor and I have some concerns regarding security vulnerabilities. My main goal is to restrict users from creating or modifying certain fields in the database. Specifically, I only want users to be able to add or update the name and description fields for a party.

Parties.allow({
  insert: function (userId, party) {
    return userId && party.owner === userId;
  },
  update: function (userId, party, fields, modifier) {
    return userId && party.owner === userId;
  },
});

I came across similar code in an Angular Meteor tutorial. However, it seems like individuals could potentially add any arbitrary field through the browser console using Minimongo. Is there a straightforward way for me to specify which fields are acceptable, and reject any inserts or updates that do not adhere to those defined fields? For updates, I thought of implementing a basic function:

function ensureFieldsAreOk(acceptableFields, fieldsInQuestion){
    for(i = 0; i < fieldsInQuestion.length; ++i){
        if(acceptableFields.indexOf(fieldsInQuestion[i]) === -1){
           console.log("Hacking attempt detected");
           return false;
        }
    }
    return true;
}

A similar approach could be used for the insert command by utilizing the same function with Object.keys(party) as the list of acceptable fields.

I highly doubt that I am the first person to encounter this issue, so there must be a standard method for addressing this concern.

Answer №1

If you want to control which fields are linked to a collection, one approach is to utilize and

These packages allow you to specify fields, their data types, default values, and various other settings.

To restrict a user from only updating specific fields, you can implement validation checks using the fieldNames parameter within your update permissions:

update: function (userId, doc, fieldNames, modifier) { 
    // perform validation on fieldNames here.
}

Answer №2

I find no issue with approaching it that way, and I am not aware of a more appropriate method. However, you can streamline your test significantly by using underscore:

Parties.allow({
  insert: function (userId, party) {
    return userId && party.owner === userId 
           && _.difference(_.keys(party), acceptableFields).length == 0;
  },
  update: function (userId, party, fields, modifier) {
    return userId && party.owner === userId
           && _.difference(fields, acceptableFields).length == 0
  }
});

Answer №3

Your question is valid and I will share how I approach this situation in my Meteor applications. When handling document insertion or updates, I utilize a screening process to ensure security. The methods for insertion and update differ based on the parameters passed to the permissions functions. I recommend implementing code similar to the following, tailored to your specific criteria:

Parties.allow({
    insert: function(userId, doc) {
        var allow = true;

        if(!userId || doc.owner !== userId) {
            allow = false;
        }

        Object.keys(doc).forEach(function(docKey) {
            if(acceptableFields.indexOf(docKey) < 0) {
                allow = false;
            }
        });

        return allow;
    },
    update: function(userId, doc, fieldNames, modifier) {
        var allow = true;

        if(!userId || doc.owner !== userId) {
            allow = false;
        }

        fieldNames.forEach(function(fieldName) {
            if(acceptableFields.indexOf(fieldName) < 0) {
                allow = false;
            }
        });

        return allow;
    }
});
In the provided code snippet, I have included checks to verify if the user is logged in and the owner of the document being manipulated in the database. The insertion function directly reviews the document's keys and fails if any are not acceptable. For the update function, examination is done on the field names parameter instead of the modified document. If deeper key checks are needed, it can be accomplished by scrutinizing the modifier parameter. Referencing this section of the Meteor documentation can provide more insights on crafting a final solution. I have written this response using generic Javascript to offer flexibility. Feel free to explore extensions like Underscore or other libraries for further enhancements.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Omit for the exclusion of nested properties within a TypeScript interface

One of the components in a library I am using is defined like this: export interface LogoBoxProps { img: React.ReactElement<HTMLImageElement>, srText?: string, href?: LinkProps['href'] } export type LogoBoxType = React.FC<React.HT ...

What strategies can be used to efficiently perform Asynchronous Operations on a high volume of rows in a particular database table?

I am looking to perform Asynchronous Operations on every row of a specific database table, which could potentially contain 500,000, 600,000, or even more rows. My initial approach was: router.get('/users', async (req, res) => { const users = ...

Set the class of the list item to "active" class

My approach to styling involves using a UL and li class to contain form selection options. I plan on hiding the radio button and using its value upon form submission. I have managed to enable checking the radio box when the <li> is clicked, but for s ...

Tips on showing a specific div when a button is clicked using jQuery and Bootstrap

In my button group, I have four buttons and I need one specific button to display certain div content when clicked. The displayed content should be based on which button is clicked. Is there a way to achieve this using Twitter Bootstrap jQuery in ASP.NET ...

Access the extended controller and call the core controller function without directly interacting with the core controller

i have a core controller that contains an array called vm.validationTypes with only 2 objects. I need to add 3 or 4 more objects to this array. to achieve this, i created another controller by extending the core controller: // CustomValidation angular.m ...

Performing data manipulation in MongoDB using Node.js, Express, and Mongoose

import mongoose from "mongoose"; const productSchema = mongoose.Schema( { name: { type: String, required: true }, category: { type: mongoose.Schema.Types.ObjectId, ref: "Category" ...

Having difficulties in Vue while attempting to access a particular row

I encountered an error message stating Uncaught TypeError: snapShotChnaged.forEach is not a function. My goal is to retrieve specific row data, which is why I am utilizing the doc method. retrieveSpecificDonation() { firestore .collection('d ...

What is the most effective method for transforming a space-separated list of classes into a jQuery selector?

Is there a quick and efficient method for converting a space-separated list of classes like: classOne classTwo classThree into a selector such as: $('.classOne .classTwo .classThree') I am considering utilizing either a loop to construct a se ...

Setting a variable in Angular after a successful AJAX call

Working on a new small application and experimenting with Angular. Encountering an issue where I am making an AJAX GET request upon clicking a button. After receiving the response, I want to set a variable to hold the result, but for some reason the variab ...

Creating a set of labels using values derived from a collection of objects

Looking for advice on how to loop through a Serialized JSON string using an ajax call in JavaScript. I have 8 labels set up and want to assign each key and value from the JSON string to a different label. Any guidance or feedback is appreciated! I'm ...

Access an HTML page programmatically using JavaScript

Make sure to have a confirmation window pop up before submitting the form, and after confirming submission (by clicking OK), redirect to a confirmation page. Here's an example code snippet: <button type="submit" value="Save" id="Save" onclick="cl ...

Angular JS provides a useful input directive called ng-pattern that allows developers to apply regular

Seeking help to validate an IP Address in a text box using ng-pattern. CODE: <input name="machinestodiscover" type="text" ng-model="machinestodiscover" ng-minlength="7" ng-maxlength="15" ng-pattern="/\b([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})[. ...

Unveiling the hidden: Leveraging Python to extract elements not visible in HTML, yet present in Chrome's "Inspect Element" tool

Hello Python Experts! I'm diving into the world of Python and working on a program to retrieve data from a webpage. If the page returned all the information in its HTML source, there wouldn't be an issue as it's easily viewed in Chrome. Howe ...

Unbounded AngularJS 1.x looping of Ag-grid's server-side row model for retrieving infinite rows

I am obtaining a set of rows from the server, along with the lastRowIndex (which is currently at -1, indicating that there are more records available than what is being displayed). The column definition has been created and I can see the column headers in ...

Infinite dice roller for a six-sided die

Looking for assistance with a School JavaScript assignment focusing on creating a 6-sided dice roller program? Need some guidance on how to approach this task? The program should allow users to choose how many dices to roll, ranging from 1 to 5. The sum o ...

Complete circular gauge in Ionic

Encountering an issue when attempting to incorporate a complete circle Gauge/Gage in Ionic, as the gauge fails to display. Has anyone managed to successfully include a full circle Gauge in Ionic similar to this: https://i.sstatic.net/OKcpD.jpg Came acro ...

Unable to bring in a TypeScript library that was downloaded from a GitHub fork repository

Currently, I am working on developing a GitHub app using the probot library. However, I have encountered an obstacle as outlined in this particular issue. It seems that probot does not offer support for ESM modules, which are crucial for my app to function ...

What are the steps to storing numerical inputs as variables using jQuery and then using them to perform calculations in order to update the input numbers

Currently, I am in the process of creating a BMI calculator using HTML and jQuery. <form id="bmiCalculator"> <fieldset> <legend>BMI Calculator:</legend> <p> <label>Height: ...

What is the process for connecting two elements in a MongoDB database?

My latest project involves creating a MERN stack app centered around cafe reviews. I want to add a feature where users can click on a cafe name to view all the reviews for that specific cafe. Any tips on how I can achieve this? Database Structure in Mong ...

Adjust the contents of a DIV depending on which Toggle button is selected

When a user clicks on either "Twin Bed" or "King Bed", the content inside the "demand-message" should change to either "high demand" or "Only ??? rooms left". The ID will remain the same for both buttons due to existing logic. However, the message display ...