Шаблон проектирования с механизмом правил и node.js для обработки разрешений

У меня есть требование использовать механизм правил для реализации разрешений ролей в системе (может ли это быть избыточным?), Однако разрешения довольно сложны и сложны. Я запутался в том, как предоставить доступ или не использовать механизм правил.

У меня также есть сомнения относительно дизайна, который я должен использовать, чтобы реализовать его в масштабируемом и поддерживаемом виде. Так что любая помощь в разработке или объяснение мне, как использовать механизм правил, была бы отличной.

Использование nools, mongoDB, node.js в качестве бэкэнда.

Я думал о создании экземпляра механизма правил, инкапсулирующего Nools (может быть, это будет анти-шаблонная внутренняя платформа?) В начальной загрузке моего приложения node.js, и пусть он будет глобальной переменной.

что-то вроде:

'use strict';

var nools = require('nools');
var flows = require('./rule-engine.flows');

// A flow is a container of rules, so each flow could be a category of rules 
// In the same flow could have some more specific subcategories would be actionGroups?

// I'm creating a ruleEngine instance that would contain nools but I'm not sure
// if that would be a good practice, I have that to maybe encapsulate boilerplate code
// or some straight forward operations in the future.. don't sure of this.
var ruleEngine = function(){
    this.nools = nools;
};

ruleEngine.prototype.getFlowSession = function(flow){
    if(this.nools.hasFlow(flow)){
        return this.nools.getFlow(flow).getSession();
    }else{
        var fl = this.nools.flow(flow, flows[flow]);
        return fl.getSession();
    }
};

ruleEngine.prototype.createRule = function(flow, rule){
    if(this.nools.hasFlow(flow)){
    // implementation to add rules to a flow
    }
};

ruleEngine.prototype.editRule = function(flow, rule, update){};
ruleEngine.prototype.retractRule = function(flow, rule){};

//could be global object, or cache object but certainly should be a single object.    
if(!GLOBAL.ruleEngine){ 
    var ruleEngineInstance = new ruleEngine();
    GLOBAL.ruleEngine = ruleEngineInstance;
}

//module.exports = GLOBAL.ruleEngine;

править-engine.flow:

'use strict';

var flowName = function(flow){
// query the rules to database or to cache.. then add the rules to the flow.
// query bla bla function(results){
for(Var i=0; i<results.length; i++)
    flow.rule(results[i].name, results[i].constraints, results[i].action);

// alternately, I could just from the bootstrap create a flow, 
// and create a function to add, modify or retract rules of a specific flow. 
// What would be the better design approach ? or combine two approach ? 
// bring from database the first time, and later use ruleModify, 
// ruleCreate or rule retract functions.
};

module.exports = {
    flowName: flowName, 
// each would be a flow that would be a category of rules for the system
    flowName2: flowName2
};

Как использовать его для реализации разрешений, это единственный способ связать механизм правил и внешнее приложение / код через события?

Вот некоторые правила, которые я создал, чтобы поиграться (в то же время они используются для создания flowName, имитирующего правила кэширования или правила MongoDB).

var results = [
    {
        name: 'userAllow',
        constraints: [Object, 'obj', 'obj.systemRole === \'user\''],
        action: function(facts, session, next){
            session.emit('event:userAllow', {data: 'user is allow'});
            next();
        }
    },
    {
        name: 'userNotAllow',
        constraints: [Object, 'obj', 'obj.systemRole !== \'user\''],
        action: function(facts, session, next){
            session.emit('event:userNotAllow', {data: 'user is not allow'});
            next();
        }
    },
    {
        name: 'adminAllow',
        constraints: [Object, 'obj', 'obj.systemRole === \'admin\''],
        action: function(facts, session, next){
            session.emit('event:adminAllow', {data: 'admin is allow!'});
            next();
        }
    },
    {
        name: 'adminNotAllow',
        constraints: [Object, 'obj', 'obj.systemRole !== \'admin\''],
        action: function(facts, session, next){
            session.emit('event:adminNotAllow', {data: 'admin not allow'});
            next();
        }
    }
];

Итак, с помощью этих нескольких правил я просто хочу предоставить доступ, когда user.systemRole является, например, admin. Должен ли я использовать события следующим образом?

Х-метод в системе:

//validate delete with ruleEngine... supposed only admin would be able to delete
var self = this;
var session = ruleEngine.getFlowSession('flowName');
session.assert({systemRole: User.role}); //User.role = 'user' || 'admin'
session.on('event:adminAllow', function(d){
    console.log('do the job because the user is admin');
    // Delete implementation.
});
session.on('event:adminNotAllow', function(d){
    console.log('User not allow because is not admin');
});
session.on('fire',function(name){
    console.log(name);
});
session.match().then(function(){
    session.dispose();
});

Пока что у меня есть некоторые проблемы с этой реализацией. События могут запускаться более одного раза, и я не могу позволить этому запускаться дважды при операции удаления, операции создания или подобных вещах.

Итак, кроме той ошибки, которую мне нужно исправить (не знаю как) Править:

Я прокомментировал последний следующий () из моих правил, и после этого события запускаются один раз. У меня есть другие сомнения:

  1. Есть хорошие практики сломаны или анти-паттерны?
  2. это масштабируемо и легко поддерживать?
  3. Это нормальный способ работы с двигателями правил?
  4. Плюсы и минусы этой реализации?
  5. Есть ли способ лучше?

Заранее благодарю за любую помощь.

1 ответ

Вы решили использовать nools? Если нет, то существует гораздо более простая (IMHO) опция для создания системы контроля доступа с использованием node_acl.

Система контроля доступа основана на трех вещах, ролях; ресурсы и разрешения. Вы определяете определенные роли и ресурсы, а затем просто устанавливаете разрешения каждой роли для каждого ресурса. Например, вы можете иметь роль "администратор" и установить разрешение "изменять" на ресурсе "Конфигурация системы". Тогда все, что вам нужно сделать, это назначить пользователей ролям по мере необходимости

Я рад предоставить вам пример кода, если хотите, но вы можете проверить учебник, который я написал по созданию системы контроля доступа для nodejs.

Другие вопросы по тегам