dispatch:configuration

v0.0.6Published 10 years ago

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

dispatch:configuration

A Meteor package that provides a simple API for working with cascading app configurations.

A Simple Example

Let's suppose you want to allow users to configure a setting within your app. After they have changed the setting, you want to use their choice, but until then you want to use a default.

First we call Configuration.setSchema in common (both client and server) startup code:

1Configuration.setSchema(new SimpleSchema({
2  hideAlerts: {type: Boolean}
3}));

You can also call Configuration.setSchemaForPrefix if you want to set the schema only for a certain nested property. This is useful if you have packages that define their own configuration.

1Configuration.setSchemaForPrefix('myPrefix', newSimpleSchema({
2  propertyUniqueToThisPackage:{type:String}
3}));

Next we call Configuration.setDefault in server code to define the default values for all settings.

1Configuration.setDefault({
2  hideAlerts: false
3});

And later you can set the default for a prefix:

1Configuration.setDefaultForPrefix('myPrefix', {
2  propertyUniqueToThisPackage:'foo'
3});

Now when we want to get the settings for user "ABC", we can do this in either client or server code:

1var shouldHideAlerts = Configuration.user('ABC').hideAlerts;

And to change the user's settings (overriding the defaults) in client or server code, you only have to set the property and the database will be updated:

1Configuration.user('ABC').hideAlerts = true;

This relies on the dispatch:bound-document package to work. You can't set object properties or properties within arrays with this method. If you need to do so, you can call Configuration.setForEntity to replace the whole user config with a new one:

1Configuration.setForEntity('user', 'ABC', {
2  hideAlerts: true
3});

A Complex Example

There is a default user entity type, but you can override it to add additional layers of inheritance. Call Configuration.addEntityType in common code for each entity type, including user. Here is an example where users inherit their configuration from the organization they belong to.

1Configuration.addEntityType('organization', {
2  inherit: 'default',
3  publish: function (userId) {
4    // must return id or array of ids
5    if (!userId) return;
6
7    var user = Meteor.users.findOne(userId);
8    if (!user) return;
9
10    return user.organization_id;
11  },
12  write: function (userId, id) {
13    // must return true or false
14    if (!userId) return false;
15
16    var user = Meteor.users.findOne(userId);
17    if (!user) return false;
18
19    return user.organization_id === id;
20  }
21});
22
23// We override the default user entity type in order to specify inheritance from org
24Configuration.addEntityType('user', {
25  inherit: function (id) {
26    // must return [entityType, entityId] or "default"
27    var user = Meteor.users.findOne(id, {
28      fields: {
29        organization_id: 1
30      }
31    });
32    if (!user || !user.organization_id) return 'default';
33
34    return ['organization', user.organization_id];
35  },
36  publish: function (userId) {
37    // must return id or array of ids
38    return userId;
39  },
40  write: function (userId, id) {
41    // must return true or false
42    return userId === id;
43  }
44});

There are lots of possibilities. You could do role-based configuration where users inherit from role entity types like admin or manager, which in turn inherit from default.

Configuration.addEntityType Options

  • inherit A function that returns [entityType, entityId] to inherit from or "default". Receives the entityId as first argument and any options you pass to getForEntity are provided as the second argument, allowing you to do complex inheritance based on calling context if necessary. For inheriting from the default configuration, you can set this to the string "default" instead of a function.
  • write A function that receives the userId and entityId and returns true or false to allow or disallow updating it from the client
  • publish A function that receives the userId and returns the entityId or array of entityIds that should be published for this type, or returns undefined for none
  • cannotOverride An array of fields in the schema that cannot be overridden (must inherit) for this entity type

Security for Editing Defaults From Client

To allow calling Configuration.setDefault from client code for some users, define a role checking function using Configuration.canEditDefault in server code. This is like the write function for the default entity.

1Configuration.canEditDefault(function (userId) {
2  if (!userId) return false;
3
4  var userRole = new Roles.User(userId);
5  return userRole.is(Roles.ADMIN);
6});

Edit Form

You can render a form for creating or updating entity configuration like this:

{{> configurationEditForm entityType="user" entityId=entityId}}

To render a form for editing defaults, specify entityType="default", specify no entityId, and be sure that you have defined a security function using Configuration.canEditDefault.

This uses a quickForm. Refer to aldeed:autoform for details.

Limitations

Currently all entity IDs must be strings and must not contain the underscore character.