Skip triggers while doing migrations

Hei,

we are using defined schemas, migrations and cloud code. One issue we are currently run into is that the migrations (defined in afterMigration) also trigger any defined triggers in cloud code (e.g. beforeSave). As some of the logic in the triggers is only valid during runtime and normal requests, we would like to skip triggers for changes performed in migrations. Each migration step would need to ensure necessary logic and cannot rely on trigger logic.

We digged through the code and were able to register cloud code later in the serverStartComplete method which is executed after migrations, instead of directly registering all cloud methods via the cloud option.

Is that a valid option, are there downsides (security wise)? Of course, the cloud functions would be available later - after the migrations are done, but that’s ok for us. Do you see other options on how to disable triggers for migration changes? With our setup, we cannot skip triggers for master key requests.

Registering cloud code via serverStartComplete can lead to potential issues as the server can receive requests from clients before Parse Server has registered the cloud hooks (this was the main reason why we evolved the startup method in Parse Server V6). If your triggers enforce additional business logic or security, this logic can be bypassed if the client calls the server at the right time. For a single instance deployment this isn’t a major concern (unless the server is constantly restarted), but for distributed environments this can be problematic as new instances are deployed.

Let’s say you have a simple beforeSave trigger of:

Parse.Cloud.beforeSave("TestObject", req => {
  throw "TestObjects cannot be saved"
});

If this is registered after the express endpoint is mounted, the cloud trigger will not run for any client calls in that period.

You could provide context to the cloud cloud call such as:

Parse.Cloud.beforeSave("TestObject", req => {
  if (req.master && req.context.skip) {
    return;
  }
  throw "Cannot save";
});

And can call with .save(null, {context: {skip: true}})

Why aren’t you choosing to run the migrations separately and ignore the runtime of the current process? My understanding is that you are performing migrations from the same process while it is running.

Thanks @dblythy , this is exactly what we were also thinking of and saw the potential risk in it. We are currently in a single instance scenario and we are only using cloud functions for our clients (though someone could potentially use the server via normal queries).

We also considered using context to pass in a certain flag to all triggers, but as we have a lot of triggers that would mean that all of them need to be modified with this logic and we would always make sure that this check is present, as we simply don’t want to run trigger logic during migration code. I don’t like the idea of mixing normal business logic with database migration logic…I prefer to keep that separated.

We have now also rewritten the migration to work directly in the DB, so that the triggers wouldn’t be called anyway.

The new startup method seems interesting and would also remove the issue I guess as we can mount the server on express after everything is finished. We plan to upgrade soon anyway.

@rgunindi
I guess you mean to run mongo schema migrations independent from Parse right? For sure, that would be another option and maybe even better, but for now we kept our migrations simple and just used the Parse Server features for it.

1 Like

Am new to parse am use to firebase but I just like the way parse structure things. I just want to suggest that _User objectId should be created by the system but other Class you should allow us to specify custom objectid our self at the state of creating the data but the objectid may not be changed. Because in some cases we might want to use user objectid as class objectid.

For example

var uuid= parsedb.objects.objectid// generating unique id

Just like the way firebase work I think it will make it more easy to work with. Because using querybuilder everytime with loop to get list is somehow

Work with flutter is it possible to use parse with stream builder please help. Because sometimes I may want to get a stream, of a single data snapshot. Instead of generating query and now monitoring the query with live query on create, update, delete etc for very class I want to listen to it update. Is somehow stressful. Please help how can I connect it with stream builder,

Yes, i mean mongo schema migration. If you need a help I can help you

I think you should write a dynamic structure for all classes.