jaynp
jaynp

Reputation: 3325

Parse-Server prevent fields from being added automatically

Right now, if I add a field to a Parse object and then save it, the new column shows up in the Parse dashboard.

For example, after running:

let media = new Parse.Object("Media");
media.set("foo", "bar");
await media.save();

I will have a new column called foo.

Is it possible to prevent this from happening?

Upvotes: 1

Views: 694

Answers (3)

addie233
addie233

Reputation: 11

Below code works find by looping through all classes to create a beforeSave event then we check if the new field added to the class exists in the schema. also you can use this tool https://github.com/fakhrullah/parse-dbtool to create migrations for your db.

    async function getAllClasses() {
      try {
        const schemas = await Parse.Schema.all();
        const classNames = schemas.map((schema) => schema.className);
        return classNames;
      } catch (error) {
        console.error("Error fetching class list:", error);
      }
    }
    
    getAllClasses().then((classes) => {
      classes.forEach((className) => {
        Parse.Cloud.beforeSave(className, async (request) => {
          const { object } = request;
          const schema = await new Parse.Schema(className).get();
    
          const objectKeys = Object.keys(object.toJSON());
          const classKeys = Object.keys(schema.fields);
    
          const missingKeys = objectKeys.filter((key) => !classKeys.includes(key));
    
          if (missingKeys.length > 0) {
            throw new Parse.Error(
              Parse.Error.INVALID_KEY_NAME,
              `Columns: ${missingKeys.join(", ")} do not exist in schema`
            );
          }
        });
      });
    });

Upvotes: 0

user2493235
user2493235

Reputation:

Yes. This can be done using class-level permissions, which allow you to prevent fields being added to classes.

Parse lets you specify what operations are allowed per class. This lets you restrict the ways in which clients can access or modify your classes.

...

Add fields: Parse classes have schemas that are inferred when objects are created. While you’re developing your app, this is great, because you can add a new field to your object without having to make any changes on the backend. But once you ship your app, it’s very rare to need to add new fields to your classes automatically. You should pretty much always turn off this permission for all of your classes when you submit your app to the public.

Upvotes: 2

Jake T.
Jake T.

Reputation: 4378

You would have to add a beforeSave trigger for every one of your classes, keep a schema of all your keys, iterate over the request.object's keys, and see if there are any that do not belong in your schema. You can then either un-set them and call response.success(), or you can call response.error() to block the save entirely, preferably with a message indicating the offending field(s).

const approvedFields = ["field1", "field2", "field3"];

Parse.Cloud.beforeSave("MyClass", function(request, response) {
    let object = request.object;
    for( var key in object.dirtyKeys() ) {
        if( approviedFields.indexOf(key) == -1 ) return response.error(`Error: Attempt to save invalid field: ${key});
    }
    response.success();
});

Edit:

Since this got a little attention, I thought I'd add that you can get the current schema of your class. From the docs: https://docs.parseplatform.org/js/guide/#schema

// create an instance to manage your class
const mySchema = new Parse.Schema('MyClass');

// gets the current schema data
mySchema.get();

It's not clear if that's async or not (you'll have to test yourself, feel free to comment update the answer once you know!)

However, once you have the schema, it has a fields property, which is an object. Check the link for what those look like.

You could validate an object by iterating over it's keys, and seeing if the schema.fields has that property:

Parse.Cloud.beforeSave('MyClass', (request, response) => {
    let object = request.object;
    for( var key in object.dirtyKeys() ) {
        if( !schema.fields.hasOwnProperty(key) ) < Unset or return error >
    }
    response.success();
}

And an obligatory note for anyone just starting with Parse-Server on the latest version ,the request scheme has changed to no longer use a response object. You just return the result. So, keep that in mind.

Upvotes: 0

Related Questions