2.8 KiB
Collection Exposure
In order to use Collection.createQuery client-side and fetch it or subscribe to it. You must expose it server side.
// server side.
Collection.expose();
// or with a custom firewall
Collection.expose((filters, options, userId) => {
if (!isAnAdmin(userId)) {
filters._id = userId;
}
// you also have control over options, if you may need to control the limits of data fetching.
});
Collection.findSecure(filters, options, userId) // if userId !== undefined, it will apply the firewall.
Exposing a collection does the following things:
- Creates a method called: exposure_{collectionName} which accepts a query
- Creates a publication called: exposure_{collectionName} which accepts a query and uses reywood:publish-composite to achieve reactive relationships.
- If firewall is specified, it extends collection with a method called findSecure in which the firewall is executed if specified.
Note: If userId is undefined, firewall will not be applied. if userId is null or String, it will be applied. The reason for this is because on server-side you may not want this restriction when fetching a query.
When using the query, if the nested collections are exposed (have a findSecure method), then the firewall will be applied.
In the exposed method and publication userId is passed when recursively fetching (or composing) the data. If the user is not logged in, userId is null.
Example
Users.expose((filters, options, userId) => {
if (!isAnAdmin(userId)) {
filters._id = userId;
}
});
Comments.expose((filters, options, userId) => {
if (!isAnAdmin(userId)) {
filters.userId = userId;
filters.isPrivate = false;
}
});
Doing a query as a non-admin (Client Side):
const query = Users.createQuery({
comments: {
$filters: {isPrivate: true}
}
});
query.fetch((err, res) => {
// res will contain only isPrivate: false comments because the firewall will override the filters.
});
However, if you do it server side:
const data = query.fetch() // will not care about the firewall at all.
Restrict fields easily
The reason for this function is that MongoDB queries do not allow fields like:
{
iWantThisField: 1,
iDontWantThisOne: 0
}
Using this function removes a bit of boilerplate code for you.
import {restrictFields} from 'meteor/cultofcoders:grapher';
Users.expose((filters, options, userId) => {
restrictFields(options, ['services', 'createdAt'];
});
The code above will clean "filters", "sort" and "fields", in this way you won't be exposing unwanted information about your data.