latest changes for demo

This commit is contained in:
Dominic Bosch 2013-12-10 23:44:28 +01:00
parent f60220c2b8
commit 8aa6d1245a
12 changed files with 191 additions and 68 deletions

View file

@ -17,10 +17,11 @@ Getting started
**Prerequisites:**
- node.js (find it [here](http://nodejs.org/))
- *(optional) Pygments if you want to generate the doc:
`sudo apt-get install python-setuptools` and then
`sudo easy_install Pygments`*
- *(optional) [CoffeeScript](http://coffeescript.org/), if you want to develop
and compile from coffee sources:*
sudo npm -g install coffee-script
and compile from coffee sources: `sudo npm -g install coffee-script`*
Clone project:

View file

@ -300,16 +300,18 @@ exports.getEventModules = ( cb ) ->
getSetRecords 'event-modules', exports.getEventModule, cb
###
Store a string representation of he authentication parameters for an event module.
Store a string representation of user-specific parameters for an event module.
@public storeEventAuth( *userId, moduleId, data* )
@public storeEventParams( *userId, moduleId, data* )
@param {String} userId
@param {String} moduleId
@param {Object} data
###
exports.storeEventAuth = ( userId, moduleId, data ) =>
log.print 'DB', 'storeEventAuth: ' + userId + ':' + moduleId
@db.set 'event-auth:' + userId + ':' + moduleId, hash(data),
# TODO is used, remove unused ones
exports.storeEventParams = ( userId, moduleId, data ) =>
log.print 'DB', 'storeEventParams: ' + userId + ':' + moduleId
# TODO encryption based on user specific key?
@db.set 'event-params:' + moduleId + ':' + userId, encrypt(data),
replyHandler 'storing event auth ' + userId + ':' + moduleId
###
@ -337,10 +339,12 @@ Store a string representation of a rule in the DB.
@param {String} id
@param {String} data
###
exports.storeRule = ( id, data ) =>
exports.storeRule = ( id, user, data ) =>
log.print 'DB', 'storeRule: ' + id
@db.sadd 'rules', id, replyHandler 'storing rule key ' + id
@db.set 'rule:' + id, data, replyHandler 'storing rule ' + id
@db.sadd 'rules', id + ':' + user, replyHandler 'storing rule key "' + id + ':' + user + '"'
@db.sadd 'user:' + user + ':rules', id, replyHandler 'storing rule key to "user:' + user + ':rules"'
@db.sadd 'rule:' + id + ':users', user, replyHandler 'storing user key to "rule:' + id + ':users"'
@db.set 'rule:' + id + ':' + user, data, replyHandler 'storing rule "' + id + ':' + user + '"'
###
Query the DB for a rule and pass it to the callback(err, obj) function.

View file

@ -254,6 +254,7 @@ exports.handleUserCommand = ( req, resp ) ->
body += data
req.on 'end', ->
obj = qs.parse body
console.log obj
if typeof objUserCmds[obj.command] is 'function'
objUserCmds[obj.command] req.session.user, obj, answerHandler req, resp
else

View file

@ -387,18 +387,18 @@ DB Interface
};
/*
Store a string representation of he authentication parameters for an event module.
Store a string representation of user-specific parameters for an event module.
@public storeEventAuth( *userId, moduleId, data* )
@public storeEventParams( *userId, moduleId, data* )
@param {String} userId
@param {String} moduleId
@param {Object} data
*/
exports.storeEventAuth = function(userId, moduleId, data) {
log.print('DB', 'storeEventAuth: ' + userId + ':' + moduleId);
return _this.db.set('event-auth:' + userId + ':' + moduleId, hash(data), replyHandler('storing event auth ' + userId + ':' + moduleId));
exports.storeEventParams = function(userId, moduleId, data) {
log.print('DB', 'storeEventParams: ' + userId + ':' + moduleId);
return _this.db.set('event-params:' + moduleId + ':' + userId, encrypt(data), replyHandler('storing event auth ' + userId + ':' + moduleId));
};
/*
@ -432,10 +432,12 @@ DB Interface
*/
exports.storeRule = function(id, data) {
exports.storeRule = function(id, user, data) {
log.print('DB', 'storeRule: ' + id);
_this.db.sadd('rules', id, replyHandler('storing rule key ' + id));
return _this.db.set('rule:' + id, data, replyHandler('storing rule ' + id));
_this.db.sadd('rules', id + ':' + user, replyHandler('storing rule key "' + id + ':' + user + '"'));
_this.db.sadd('user:' + user + ':rules', id, replyHandler('storing rule key to "user:' + user + ':rules"'));
_this.db.sadd('rule:' + id + ':users', user, replyHandler('storing user key to "rule:' + id + ':users"'));
return _this.db.set('rule:' + id + ':' + user, data, replyHandler('storing rule "' + id + ':' + user + '"'));
};
/*

View file

@ -75,10 +75,19 @@ function loadRulesFromDB() {
* @param {Object} objModule the action module object
*/
exports.loadActionModule = function(name, objModule) {
//TODO not used yet, load action modules from db for each rule per user
// TODO only load module once, load user specific parameters per user
// when rule is activated by user. invoked action then uses user specific
// parameters
log.print('EN', 'Action module "' + name + '" loaded');
listActionModules[name] = objModule;
};
exports.getActionModule = function(name) {
return listActionModules[name];
};
/**
* Add a rule into the working memory
* @param {Object} objRule the rule object
@ -160,6 +169,8 @@ function validConditions(evt, rule) {
function invokeAction(evt, action) {
var actionargs = {},
arrModule = action.module.split('->');
//TODO this requires change. the module property will be the identifier
// in the actions object (or shall we allow several times the same action?)
if(arrModule.length < 2) {
log.error('EN', 'Invalid rule detected!');
return;

View file

@ -25,7 +25,7 @@ exports.addDBLink = function(db_link) {
db = db_link;
};
exports.storeEventModule = function (user, obj, answHandler) {
exports.storeEventModule = function (objUser, obj, answHandler) {
try {
// TODO in the future we might want to link the modules close to the user
// and allow for e.g. private modules
@ -40,33 +40,78 @@ exports.storeEventModule = function (user, obj, answHandler) {
}
};
exports.getAllEventModules = function ( user, obj, answHandler ) {
exports.getAllEventModules = function ( objUser, obj, answHandler ) {
db.getEventModules(function(err, obj) {
if(err) answHandler.answerError('Failed fetching event modules: ' + err.message);
else answHandler.answerSuccess(obj);
});
};
exports.storeActionModule = function (user, obj, answHandler) {
exports.storeActionModule = function (objUser, obj, answHandler) {
var m = ml.requireFromString(obj.data, obj.id);
obj.methods = Object.keys(m);
answHandler.answerSuccess('Thank you for the action module!');
db.storeActionModule(obj.id, obj);
};
exports.getAllActionModules = function ( user, obj, answHandler ) {
exports.getAllActionModules = function ( objUser, obj, answHandler ) {
db.getActionModules(function(err, obj) {
if(err) answHandler.answerError('Failed fetching action modules: ' + err.message);
else answHandler.answerSuccess(obj);
});
};
exports.storeRule = function (user, obj, answHandler) {
log.print('MM', 'implement storeRule');
answHandler.answerSuccess('Thank you for the rule!');
exports.storeRule = function (objUser, obj, answHandler) {
var cbEventModule = function (lst) {
return function(err, data) {
if(err) {
err.addInfo = 'fetching event module';
log.error('MM', err);
}
if(!err && data) {
if(data.params) {
lst.eventmodule = data.params;
}
}
if(--semaphore === 0) answHandler.answerSuccess(lst);
};
};
var cbActionModule = function (lstParams) {
return function(err, data) {
if(err) {
err.addInfo = 'fetching action module';
log.error('MM', err);
}
if(!err && data) {
if(data.params) {
lstParams.actionmodules[data.id] = data.params;
}
}
if(--semaphore === 0) answHandler.answerSuccess(lstParams);
};
};
var semaphore = 1;
var lst = {
eventmodule: null,
actionmodules: {}
};
try {
var objRule = JSON.parse(obj.data);
for(var i = 0; i < objRule.actions.length; i++) {
semaphore++;
db.getActionModule(objRule.actions[i].module.split('->')[0], cbActionModule(lst));
}
db.getEventModule(objRule.event.split('->')[0], cbEventModule(lst));
db.storeRule(objRule.id, objUser.username, obj.data);
} catch(err) {
answHandler.answerError(err.message);
log.error('MM', err);
}
};
// FIXME REMOVE
/*
* Legacy file system loaders
*/
@ -91,7 +136,7 @@ exports.loadRulesFromFS = function(args, answHandler) {
log.print('ML', 'Loading ' + arr.length + ' rules:');
for(var i = 0; i < arr.length; i++) {
txt += arr[i].id + ', ';
db.storeRule(arr[i].id, JSON.stringify(arr[i]));
db.storeRule(arr[i].id, 'james-t', JSON.stringify(arr[i]));
// funcLoadRule(arr[i]);
}
answHandler.answerSuccess('Yep, loaded rules: ' + txt);

View file

@ -101,10 +101,7 @@ Request Handler
resp.send('Thank you for the event: ' + obj.event + ' (' + obj.eventid + ')!');
return db.pushEvent(obj);
} else {
resp.writeHead(400, {
"Content-Type": "text/plain"
});
return resp.send('Your event was missing important parameters!');
return resp.send(400, 'Your event was missing important parameters!');
}
});
};
@ -308,6 +305,7 @@ Request Handler
return req.on('end', function() {
var obj;
obj = qs.parse(body);
console.log(obj);
if (typeof objUserCmds[obj.command] === 'function') {
return objUserCmds[obj.command](req.session.user, obj, answerHandler(req, resp));
} else {

View file

@ -1,7 +1,7 @@
// Generated by CoffeeScript 1.6.3
/*
Rules Server
Server
============
>This is the main module that is used to run the whole server:

View file

@ -163,6 +163,8 @@ function validConditions(evt, rule) {
function invokeAction(evt, action) {
var actionargs = {},
arrModule = action.module.split('->');
//TODO this requires change. the module property will be the identifier
// in the actions object (or shall we allow several times the same action?)
if(arrModule.length < 2) {
log.error('EN', 'Invalid rule detected!');
return;
@ -170,6 +172,7 @@ function invokeAction(evt, action) {
var srvc = listActionModules[arrModule[0]];
if(srvc && srvc[arrModule[1]]) {
//FIXME preprocessing not only on data
//FIXME no preprocessing at all, why don't we just pass the whole event to the action?'
preprocessActionArguments(evt.payload, action.arguments, actionargs);
try {
if(srvc[arrModule[1]]) srvc[arrModule[1]](actionargs);

View file

@ -31,11 +31,11 @@ exports.myOwnEventFunction = function( callback ) {
<script type = "text/template" id="templ_params">
{
username: {
description: "The username for the Web API"
"username": {
"description": "The username for the Web API"
},
password: {
description: "The password for the Web API"
"password": {
"description": "The password for the Web API"
}
}
</script>
@ -57,10 +57,10 @@ exports.myOwnEventFunction = function( callback ) {
<p>
<textarea id="textarea_module" rows="20" cols="100"> </textarea>
</p>
<p>
<!-- <p>
Description of module:<br />
<textarea id="textarea_description" rows="2" cols="100">This module does...</textarea>
</p>
</p> -->
<p>
<!-- <input id="checkbox_public" type="checkbox"> Module is public, reusable for everybody<br />-->
<input id="checkbox_params" type="checkbox"> Module requires user-specific parameters
@ -87,23 +87,29 @@ exports.myOwnEventFunction = function( callback ) {
else {
var obj = {
id: $('#input_id').val(),
data: $('#textarea_module').val(),
description: $('#textarea_description').val(),
data: $('#textarea_module').val()
// description: $('#textarea_description').val(),
// ispublic: $('#checkbox_public').is(':checked')
};
if($('#checkbox_params').is(':checked')) {
obj.params = $('#textarea_params').val();
try {
if($('#checkbox_params').is(':checked')) {
//TODO if syntax error we should make better info's
JSON.parse($('#textarea_params').val());
obj.params = $('#textarea_params').val();
}
if($('#select_type').val() === '0') obj.command = 'store_action';
else obj.command = 'store_event';
$.post('/usercommand', obj)
.done(function(data) {
alert(data);
})
.fail(function(err) {
console.error(err);
alert('Posting of module failed: ' + err.responseText);
});
} catch(err) {
alert(err);
}
if($('#select_type').val() === '0') obj.command = 'store_action';
else obj.command = 'store_event';
$.post('/usercommand', obj)
.done(function(data) {
alert(data);
})
.fail(function(err) {
console.error(err);
alert('Posting of module failed: ' + err.responseText);
});
}
});
$('#checkbox_params').click(function() {

View file

@ -3,6 +3,22 @@
<head>
<title>Forge A Rule</title>
{{{head_requires}}}
<script type = "text/template" id="templ_rule">
{
"id": "rule_id",
"event": "custom",
"condition": { "property": "yourValue" },
"actions": [
{
"module": "probinder->newContent",
"arguments": {
"content": "Rule#2: $X.subject"
}
}
]
}
</script>
</head>
<body>
{{{div_menubar}}}
@ -10,40 +26,76 @@
<div id="pagetitle">Hi {{user.username}}, forge your own rules!</div>
<p>
<div id="div_left">
<textarea id="textarea_module" rows="20" cols="100"> </textarea>
<input type="hidden" id="command" value="store_rule" />
<textarea id="textarea_rule" rows="20" cols="60"> </textarea>
<p id="required_params">
</p>
<p>
<button id="but_submit">save</button>
</p>
</div>
<div id="div_right">
<div id="div_middle">
<p><b>Available Event Modules:</b></p>
<ul> </ul>
</div>
<div id="div_right">
<p><b>Available Action Modules:</b></p>
<ul> </ul>
</div>
</p>
</div>
<script type="text/javascript">
$('#but_submit').click(function() {
// var req_fields =
var obj = {
command : 'store_rule',
data: $('#textarea_event').val()
data: $('#textarea_rule').val()
};
$.post('/usercommand', obj)
// $.post('/usercommand', $('form#rules_form').serialize())
.done(function(data) {
alert(data);
$('#required_params').children().remove();
if(data.success) {
alert(data.info);
} else {
if(data.eventmodule) {
var oEM = JSON.parse(data.eventmodule);
$('#required_params').append($('<p>').html($('<b>Required Event Module Parameters</b>')));
for(var el in oEM){
var inp = '<b>' + el + ': </b><input type="password" id="em_'+oEM[el]+'" />('+oEM[el].description+')';
$('#required_params').append($('<p>').html(inp));
}
}
for(var el in data.actionmodules) {
$('#required_params').append($('<p>').html($('<b>Required Action Module "'+el+'" Parameters</b>')));
var oAM = JSON.parse(data.actionmodules[el]);
for(var ael in oAM){
var inp = '<b>' + ael + ': </b><input type="password" id="am_'+ael+'_'+oAM[ael]+'" />('+oAM[ael].description+')';
$('#required_params').append($('<p>').html(inp));
}
}
}
})
.fail(function(err) {
console.log(err);
alert('Posting of rule failed: ' + err.responseText);
});
});
$.post('/usercommand', { command: 'get_actionmodules' })
$.post('/usercommand', { command: 'get_eventmodules' })
.done(function(data) {
for(var el in data) {
for(var mod in data) {
var mthds = data[mod].methods;
if(mthds) {
var arr = mthds.split(',');
for(var i = 0; i < arr.length; i++) {
$('#div_middle ul').append($('<li>').text(mod + '->' + arr[i]));
}
}
}
});
$.post('/usercommand', { command: 'get_eventmodules' })
$.post('/usercommand', { command: 'get_actionmodules' })
.done(function(data) {
for(var mod in data) {
var mthds = data[mod].methods;
@ -55,12 +107,7 @@
}
}
});
$('#input_event').focus(function() {
$('#radio_input').prop('checked', true);
});
$('#select_event').focus(function() {
$('#radio_select').prop('checked', true);
});
$('#textarea_rule').val($('#templ_rule').html());
</script>
</body>
</html>

View file

@ -49,9 +49,14 @@ textarea {
#div_left {
float: left;
padding-right: 10px;
}
#div_middle li {
font-size: 78%;
list-style-type: none;
}
#div_right li {
font-size: 78%;
list-style-type: none;
}