Design pattern nools with Node.js to resolve permissions in a system

255 views
Skip to first unread message

Rodolfo hernandez

unread,
Nov 3, 2014, 2:44:20 PM11/3/14
to no...@googlegroups.com
Hello, Im working with nools and I want to create a box of how to use nools with node.js.

Please take a look on this stackOverflow question that I did. I just realize there is not enough attention to nools in SO so I would share my concerns here in the group:

I have the requirement to use a rule engine to implement role permissions in the system ( could this be an over kill? ) how ever the permissions are kind of complicated and complex it self. I got confused in how to grant access or not using a rule-engine.
I'm also have doubts about the design that I should use in order to implement it in a scalable and maintainable way. So any help in design or explain to me how to use the rule engine would be great.
Using Nools, mongodb and node.js as my backend.

I was thinking in creating a rule engine instance encapsulating nools ( would be an anti-pattern inner platform maybe?) in the bootstrap of my node.js app and let it as a global variable.

something like:

   
 '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;



rule-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
   
};



How to use it to implement permissions? if the only way to communicate what's happen in rule engine and external code are events?
these are some rules I created just to mess about ( at the same time are the ones used to create the flowName simulating the cache rules or mongoDB rules with a pseudo schema).

   
 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();
           
}
       
}
   
];



So with this few rules, I just want to grant access when user.systemRole is admin for example.. should I use events in the following way ?

X-method in the system:

   
//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();
       
});



So this are my doubts:

 1. Have good practices broken or anti-patterns?
 2. this is scalable and easy to maintain?
 3. Is the normal way of working with rule-engines?
 4. Pros and Cons of this implementation?
 5. Is there a better way?

Thanks in advance for any help and if I misunderstood some of rule-engine or nools or node, please tell me.
Regards.
Reply all
Reply to author
Forward
0 new messages