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?
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.