I want to publish the social login services users have linked their accounts to, but without publishing the configuration details of these services. So, what I need is a query that gets all keys of the services subtree of the user object, but not the values of these keys.
Is there a simple way to do that with a simple Mongo query, or do I have to get the whole service configuration and create a custom publication based on the results?
Alternatively, a publish function can directly control its published record set by calling the functions added (to add a new document to the published record set), changed (to change or clear some fields on a document already in the published record set), and removed (to remove documents from the published record set). These methods are provided by this in your publish function.
There is an example before that paragraph that shows pretty much what you want, I think.
Meteor.publish("publicationsWithHTML", function (data) {
var self = this;
Publications
.find()
.forEach(function(entry) {
addSomeHTML(entry); // this function changes the content of entry
self.added("publications", entry._id, entry);
});
self.ready();
});
This is from 2014, and maybe things stopped working like that since – but if they didn’t, this gives you complete control to alter the returned document(s).
Thanks for the feedback. Yes, I solved this using observeChanges and an added hook in the meantime. However, with my current solution, I actually need two cursors in my ownUser publication: one for the user object without the service configuration (in order to not publish sensitive data to the client) and one that just observes changes on the services key, clears all data inside these keys and sends just an empty object for every service key to the client:
// publish social services, but without sensitive information
const servicesCursor = Meteor.users.find({ _id }, { fields: { services: 1 } });
const clear = (services = {}) => {
const cleared = {};
const keys = _.intersection(Object.keys(services), allServices);
keys.forEach(key => (cleared[key] = {}));
return cleared;
};
servicesCursor.observeChanges({
added: (id, fields) => this.added('users', id, { services: clear(fields.services) })
});
// publish other fields that are safe to publish
const cursor = Meteor.users.find({ _id }, { fields: allowedFields });
return cursor;
This works, but does not look very elegant. So I am still wondering if there is an easier way to do it, using just a Mongo query.
I mean the list of services keys is limited. For example you have password, email, github, facebook, twiter. You can select what key is available by project:
I need it as a publication, because it will be the signal to the user that the connection has been established. Although I might as well rely on the callback methods, I wasn’t sure if they would work reliably enough. And a publication won’t do any harm in my use-case, as I already have a publication for the user’s own profile data.