Я ставлю слой безопасности перед документно-ориентированным, и мне нужен достаточно абстрактный способ для приложения определить, какие новые документы и какие обновления существующих документов являются законными для конкретного пользователя.
Особые проблемы: документы определены (по крайней мере, в пути) как объекты JSON, поэтому правила могут быть иерархическими, поэтому механизм правил должен работать рекурсивно.Например, объект Employee может иметь подобъект под названием Compensation, а у этого подобъекта есть поле с именем PayPeriod, которое должно быть одним из «еженедельно», «раз в две недели» или «ежемесячно».- он запускает Node.js, и некоторые правила нужно читать из ввода (например, чтобы прочитать больше пользовательских данных из базы данных), поэтому он должен работать в стиле продолжения.
Итак, что я придумалазаключается в следующем: каждое правило - это функция, которая принимает текущее значение, предлагаемое новое значение и обратный вызов, который вызывается со значением, которое будет использоваться.Это значение может быть одним из двух входов или некоторым третьим значением, рассчитанным по правилу.Вот одно правило:
var nonEmpty = function(proposedValue, existingValue, callback) {
callback( (proposedValue.length > 0) ? proposedValue : existingValue);
};
Это правило позволит вам только установить или заменить это поле значением, отличным от нуля.Конечно, это имеет смысл только для строковых значений (на данный момент игнорируем списки, поэтому нам нужно правило для принудительного применения строковых значений):
var isString = function(proposedValue, existingValue, callback) {
callback( ( typeof(proposedValue) === 'string') ? proposedValue : existingValue);
};
На самом деле это кажется общей проблемой,поэтому я написал генератор правил:
var ofType = function(typeName) {
return function(proposedValue, existingValue, callback) {
callback( ( typeof(proposedValue) === typeName) ? proposedValue : existingValue);
};
};
var isString = ofType('string')
, но мне нужен способ объединения правил:
var and = function(f1, f2) {
return function(proposedValue, existingValue, callback) {
f1(proposedValue, existingValue,
function(newProposedValue) {
f2(newProposedValue, existingValue, callback);
});
};
};
var nonEmptyString = and(isString, nonEmpty);
Таким образом, правило для администратора для обновления записи Сотрудника может быть:
limitedObject({
lastName : nonEmptyString,
firstName : nonEmptyString,
compensation : limitedObject({
payPeriod : oneOf('weekly', 'biweekly', 'monthly'),
pay : numeric
}
})
limitedObject
(подобно ofType
) - это функция, генерирующая правила, которая разрешает только поля, указанные в ее аргументе, и применяет данное правило к значениям этих полей.
Итак, я написал все это, и это работает как шарм.Все мои ошибки оказались ошибками в модульных тестах!Ну, почти все из них.В любом случае, если вы читали это далеко, вот мой вопрос:
Я лихорадочно изучал монады, и мое чтение вдохновило меня на решение этой проблемы.Но действительно ли это монадическое?
(Возможные ответы: «Да», «Нет, но это нормально, потому что монады не совсем правильный подход к этой проблеме» и «Нет, и вот что нужноизменить ". Четвертые возможности также приветствуются.)