jkuester:publication-factory

v1.1.2Published 5 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

Build Status

Supporter class to create publications from a source object with minimal to no extra code.

Installation

1meteor add jkuester:publication-factory

Changelog

1.2.0

  • Allow to pass custom validator functions vor query and projection with fallback to internal default validation.

1.1.1

  • fixed check to comply auditAllArguments and still accept undefined query / projection args from subscription

1.1.0

  • lint fix using standardjs
  • merged publication arguments from two to one on order to support single object args on subscriptions

Principle

Pass in an object of your publication definitions with respect to the given API. The factory will return a function that is ready to be passed to Meteor.publish and will behave according to your configuration.

API

The create functio requires at least an object, referred as params in this guide.

Note, that params.collectionName is currently the only required property to be passed. All other properties are optional! Such a publication would default to return all documents and accepts no args from subscriptions.

All Parameters

The basic paramater pattern is

1PublicationFactory.create(params)

which can be fully broken down to the following schema:

1PublicationFactory.create({
2
3  // the collection to be published
4  collectionName: String,
5  
6  // define query behavior
7  query: {
8    
9    // describe the allowed query args 
10    // using a schema descriptiom
11    schema: Object,
12    
13    // describe the default query, the server
14    // will execute if no transform is applied
15    server: Object,
16    
17    // provide a function that conditionally applies client
18    // queries on server queries. You can also include strict
19    // or loose security checks here as a third layer of security
20    transform: Function
21  },
22  projection: {
23    
24    // describe the allowed projection args 
25    // using a schema descriptiom
26    schema: Object,
27    
28    // describe the default projection, the server
29    // will execute if no transform is applied
30    server: Object,
31    
32    // provide a function that conditionally applies client
33    // projection on server projection. You can also include strict
34    // or loose security checks here as a third layer of security
35    transform: Function
36        
37  },
38  security: {
39    
40    // explicitly disable authentication check
41    // so the publication runs also for non-registered users
42    disable: Boolean,
43    
44    // define roles that registered users need to comply
45    // in order to publish. 
46    roles: [String],
47    
48    // define a group that registered users need to comply
49    // in order to publish.
50    group: String,
51  },
52  validators: {
53    
54     // custom validation for the 
55     // client side query
56    query: Function, 
57    
58    // custom validation for the 
59    // client side projection
60    projection: Function, 
61  }
62})

params.collectionName (String)

Pass the name of a collection for which you want to publish data. If no other parameters are passed, the whole collection's data will be published.

Example

1const Cars = new Mongo.Collection('cars')
2
3const allCars = PublicationFactory.create({
4  collectionName: 'cars', // the collection to be published
5})
6
7// publishing this will
8// return all cars, and 
9// accept no args from subscriptions
10Meteor.publish("allCars", allCars)

params.query (Object)

You can define query behavior including transforming queries based on data, passed by clients.

params.query.server (Object)

You can define a static query using the server property. This is useful when your publication always publishes data by the same set of rules.

Falls back to {} if nothing is passed.

params.query.schema (Object)

Restrict client's query options using schema definition that is conform to check/Match. Basic SimpleSchema definitions can be used, too, as they both follow the property:Constructor pattern.

Complex restrictions however, can also be set using Match pattern.

params.query.transform (Function)

You can use this to define dynamic queries that respects users input and the default query on the server. You can also perform additional checks here.

Pass a function that accepts two parameters (queryClient - the current client's query object that is passed to the pub, queryServer - the default server query) and return your final query.

Example

1const Cars = new Mongo.Collection('cars');
2
3const redCarsByYear = PublicationFactory.create({
4  collectionName: 'cars', // the collection to be published
5  query: {
6    schema: { year: Number },
7    server: { color: 'red' },
8    transform(queryClient, queryServer) {
9      return Object.assign({}, { year: { $gt: queryClient.year }, queryServer})
10    }
11  }
12})
13
14// this would create a publication that
15// returns all car docs with color=red by a
16// given year
17Meteor.publish("redCarsByYear", redCarsByYear)

params.projection (Object)

Works the same way as params.query but for the projection values. Use transform to add custom logic for handling skip, limit etc.

params.security (Object)

The create method's parameter object accepts several security settings using the security property. By default each publication is checking this.userId against Meteor.users and throws an error if failing.

params.security.roles (String or [String])

Add roles (uses alanning:roles) and optional group definition to security to also check against roles. If no roles property is given, no roles check will be performed.

params.security.group (String)

Optional group definition as defined by alanning:roles.

params.security.users ([String])

  • You can add an array of user ids, named users to security in order to restrict for specific users.

This array can also be used in combination with roles where roles is first checked and then users. If a user passes the roles check but is not in the given pool of users, the check will fail. If no users property is given, no check will be performed.

params.security.disable (Boolean)

  • Add disable:true to security in order to surpass all prior mentioned security checks. In this case anyone can

subscribe to the publication and view data. Use with care!

Example

1const Cars = new Mongo.Collection('cars');
2
3const prototypeCars = PublicationFactory.create({
4  collectionName: 'cars', // the collection to be published
5  security: {
6    roles: ['viewPrototypes'],
7    group: 'researchers',
8    members: ['someUserIdHere'],
9    disable: false,
10  }
11});
12
13
14Meteor.publish("allToys", allToys);

params.validators

With version 1.2.0 it is supported to pass in custom validators. This solves the problem of providing a way for validating complex structures while keeping the package free of external dependencies.

params.validators.query

Runs a function that provides the current client query against the expected schema. Throw an error or return a falsey value in order to

Example using SimpleSchema

Note, that SimpleSchema is optional to this package and needs to be installed, if you want to use it.

1const Cars = new Mongo.Collection('cars');
2
3const carsByYearSchemaDefinition = { 
4  year: Number,
5  min: 1769,
6  max: new Date().getFullYear() 
7}
8
9const carsByYearSchema = new SimplSchema(carsByYearSchemaDefinition)
10
11const carsByYear = PublicationFactory.create({
12  collectionName: 'cars', // the collection to be published
13  query: {
14    schema: carsByYearSchemaDefinition,
15  },
16  validators: {
17    query(clientQuery, querySchema) {
18      // throws error if not valid
19      carsByYearSchema.validate(clientQuery)
20      return true
21    }
22  }
23});
24
25
26Meteor.publish("carsByYear", carsByYear);

params.validators.projection

The same principles apply to this function as for params.validators.query