0

I want to make a SimpleSchema for documents with the the following format:

{
  ...,
  permissions: {
    foo: {allow: ["user1", "user2"]},
    bar: {allow: ["admin"]},
  }
}

If foo and bar were well-known strings in the schema, I would just do this:

const PermissionsSchema = new SimpleSchema({
  allow: {type: [String]},
});

new SimpleSchema({
  ...,
  'permissions.foo': {
    type: PermissionSchema,
  },
  'permissions.bar': {
    type: PermissionSchema,
  },
})

However, in this case, there can be arbitrary string keys, not just foo and bar. The values must always match PermissionsSchema. Is there a way to express this?

Thomas
  • 174,939
  • 50
  • 355
  • 478

1 Answers1

0

Custom validators to the rescue!

import { ValidationError } from 'mdg:validation-error';

function permissionsValidator(keyRegEx) {
  if (!(keyRegEx instanceof RegExp)) {
    throw new Error('must pass a regular expression');
  }
  return function() {
    // https://github.com/aldeed/meteor-simple-schema#custom-validation
    const value = this.value;
    for (let key in value) {
      if (value.hasOwnProperty(key)) {
        if (!keyRegEx.test(key)) {
          return 'regEx';
        }
        try {
          PermissionSchema.validate(value[key]);
        } catch (ex) {
          if (ex instanceof ValidationError) {
            return ex.error;
          }
        }
      }
    }
  };
}

new SimpleSchema({
  ...,
  permissions: {
    type: Object,
    custom: permissionsValidator(/^.*$/),
    blackbox: true,
    optional: true,
    defaultValue: {},
  },
});

The error messages that come out are rubbish, though. Improvements or better strategies still welcome.

Thomas
  • 174,939
  • 50
  • 355
  • 478