2016-09-14 16:04:08 +03:00
Collection Exposure
===================
2016-09-15 09:14:15 +03:00
In order to use *Collection.createQuery* client-side and fetch it or subscribe to it. You must expose it server side.
2016-09-14 16:04:08 +03:00
```javascript
2016-09-15 09:14:15 +03:00
// server side.
2016-09-14 16:04:08 +03:00
Collection.expose();
2016-09-16 19:22:12 +03:00
2016-09-15 09:14:15 +03:00
// or with a custom firewall
2016-09-14 16:04:08 +03:00
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.
});
2016-09-16 19:22:12 +03:00
Collection.findSecure(filters, options, userId) // if userId !== undefined, it will apply the firewall.
2016-09-14 16:04:08 +03:00
```
Exposing a collection does the following things:
- Creates a method called: exposure_{collectionName} which accepts a query
2016-09-15 09:14:15 +03:00
- Creates a publication called: exposure_{collectionName} which accepts a query and uses [reywood:publish-composite ](https://atmospherejs.com/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.
2016-09-14 16:04:08 +03:00
2016-09-16 19:22:12 +03:00
Note: If userId is undefined, firewall will not be applied. if userId is null or String, it will be applied.
2016-09-14 16:04:08 +03:00
The reason for this is because on server-side you may not want this restriction when fetching a query.
2016-09-16 19:22:12 +03:00
When using the query, if the nested collections are exposed (have a findSecure method), then the firewall will be applied.
2016-09-15 09:14:15 +03:00
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.
2016-09-14 16:04:08 +03:00
Example
-------
```javascript
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):
```javascript
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:
```javascript
const data = query.fetch() // will not care about the firewall at all.
2016-09-16 19:22:12 +03:00
```
2016-09-20 10:02:55 +03:00
### 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'];
});
```
2016-09-20 12:51:30 +03:00
The code above will clean "filters", "sort" and "fields", in this way you won't be exposing unwanted information about your data.
2016-09-16 19:22:12 +03:00
### Next step
2016-09-18 17:47:30 +03:00
[Read about Query ](query.md )