Conditionally send data from server to client

Hi!

I’m trying to send the data from server to client based on a condition which relies on MongoDB data.

I am publishing a collection on server-side like this:

Meteor.publish('secureCollections', function () {
  if (this.userId) {
    const user = Meteor.users.findOne({ _id: this.userId });

    // Check against MongoDB if user is allowed to get the data
    // and if it isn't, don't send any data (e.g. unsubscribe?)
    if (!userHasPermission(user)) {
      return this.stop();
    }

    return SecureCollections.find({});
  }
  return this.ready();
});

This works fine when I start the app, but I can’t figure out how would I handle sending data from server to client when the data in MongoDB changes? What I’d like to achieve is to send the data to client only if userHasPermission(user) resolves to true and to avoid sending data to client if userHasPermission(user) resolves to false without refreshing client side. I tried to play with observing user collection changes (Meteor.users.find().observeChanges()), but I’m not sure how would I handle Meteor.publish() method when I catch a change there.

Any suggestion here is more than welcome, thanks!

I’m thinking it might be possible via observeChanges, but I’m not entirely sure. Here is an example usage for my profile method:

Meteor.publish('profile.for', function (userIdOrUsername: string) {
  check(userIdOrUsername, String)
  const sub = this
  const handle = ProfilesCollection.find(
    { $or: [{ _id: userIdOrUsername }, { username: userIdOrUsername }] },
    {
      projection: {
        birthday: 0,
        gender: 0
      },
      limit: 1,
      sort: { username: 1 }
    }
  ).observeChanges({
    added(id: string, doc: Profile) {
      if (doc.namePrivate) {
        delete doc.givenName
        delete doc.familyName
      }
      if (doc.country && !doc.country.public) delete doc.country

      sub.added('socialize:profiles', id, doc)
    }
  })
  sub.onStop(() => {
    handle.stop()
  })
  sub.ready()
})

Update: here is the docs: Collections | Meteor API Docs

According to that I think it can be useful to you.

Thanks, this looks useful!

I’m still a bit puzzled with how to publish my collection, let me share my current code…

Meteor.publish('secureCollections', async function () {
  if (this.userId) {
    const sub = this;
    const handle = Meteor.users.find({ _id: this.userId }).observeChanges({
      changed(id, fields) {
        if (userHasPermission(fields)) {  // Check changed data in `fields` object
          // How to publish SecureCollections at this point?
        }
      },
    });

    sub.onStop(() => {
      // Is this going to stop publishing SecureCollections or User collection?
      handle.stop();
    })
    sub.ready();
  }
});

To clarify maybe a bit more, I have to listen for changes in one collection (Users) but handle publishing other collection (SecureCollections) based on data from the first one.

Thanks again for looking into this!