diff --git a/coffee/dynamic-modules.coffee b/coffee/dynamic-modules.coffee index ad2c6ff..2a52ce4 100644 --- a/coffee/dynamic-modules.coffee +++ b/coffee/dynamic-modules.coffee @@ -15,11 +15,13 @@ db = require './persistence' # [events](http://nodejs.org/api/events.html) vm = require 'vm' needle = require 'needle' +request = require 'request' # - External Modules: [coffee-script](http://coffeescript.org/), # [cryptico](https://github.com/wwwtyro/cryptico) cs = require 'coffee-script' cryptico = require 'my-cryptico' +cryptoJS = require 'crypto-js' @@ -47,8 +49,12 @@ exports = module.exports = ( args ) => exports.getPublicKey = () => @strPublicKey - -issueApiCall = ( logger ) -> +# We need to wrap the callbacks in try/catch so the token does not get killed and +# other modules are not called. This will be obsolete as soon as each module +# runs in a child process +# FIXME this seems not to achieve what we expected... token gets still lost +# -> implement child processes per module. (or better per user?) +issueNeedleCall = ( logger ) -> ( method, url, data, options, cb ) -> try needle.request method, url, data, options, ( err, resp, body ) => @@ -59,6 +65,17 @@ issueApiCall = ( logger ) -> catch err logger 'Error before needle request! ' + err.message +issueRequest = ( logger ) -> + ( options, cb ) -> + try + request options, ( err, resp, body ) => + try + cb err, resp, body + catch err + logger 'Error during request! ' + err.message + catch err + logger 'Error before request! ' + err.message + logFunction = ( uId, rId, mId ) -> ( msg ) -> db.appendLog uId, rId, mId, msg @@ -88,6 +105,7 @@ exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) => err.location.first_line fTryToLoad = ( params ) => + if params try oDecrypted = cryptico.decrypt params, @oPrivateRSAkey @@ -103,7 +121,9 @@ exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) => sandbox = id: userId + '.' + modId + '.vm' params: params - needlereq: issueApiCall logFunc + needlereq: issueNeedleCall logFunc + request: issueRequest logFunc + cryptoJS: cryptoJS log: logFunc debug: console.log exports: {} diff --git a/coffee/persistence.coffee b/coffee/persistence.coffee index 076ea26..357c7d0 100644 --- a/coffee/persistence.coffee +++ b/coffee/persistence.coffee @@ -327,7 +327,7 @@ Appends a log entry. @param {String} message ### exports.appendLog = ( userId, ruleId, moduleId, message ) => - @db.append "#{ userId }:#{ ruleId }", + @db.append "#{ userId }:#{ ruleId }:log", "[#{ ( new Date ).toISOString() }] {#{ moduleId }} #{ message }\n" ### @@ -339,7 +339,7 @@ Retrieves a log entry. @param {function} cb ### exports.getLog = ( userId, ruleId, cb ) => - @db.get "#{ userId }:#{ ruleId }", cb + @db.get "#{ userId }:#{ ruleId }:log", cb ### Resets a log entry. @@ -349,8 +349,8 @@ Resets a log entry. @param {String} ruleId ### exports.resetLog = ( userId, ruleId ) => - @db.del "#{ userId }:#{ ruleId }", - replyHandler "RESET LOG '#{ userId }:#{ ruleId }'" + @db.del "#{ userId }:#{ ruleId }:log", + replyHandler "del '#{ userId }:#{ ruleId }:log'" ### Query the DB for a rule and pass it to cb(err, obj). @@ -360,7 +360,7 @@ Query the DB for a rule and pass it to cb(err, obj). @param {function} cb ### exports.getRule = ( ruleId, cb ) => - @log.info "DB | getRule: '#{ ruleId }'" + @log.info "DB | get: 'rule:#{ ruleId }'" @db.get "rule:#{ ruleId }", cb ### @@ -370,7 +370,7 @@ Fetch all rules and pass them to cb(err, obj). @param {function} cb ### exports.getRules = ( cb ) => - @log.info 'DB | Fetching all Rules' + @log.info "DB | Fetching all Rules: getSetRecords 'rules'" getSetRecords 'rules', exports.getRule, cb ### @@ -380,7 +380,7 @@ Fetch all rule IDs and hand it to cb(err, obj). @param {function} cb ### exports.getRuleIds = ( cb ) => - @log.info 'DB | Fetching all Rule IDs' + @log.info "DB | Fetching all Rule IDs: 'rules'" @db.smembers 'rules', cb ### @@ -393,9 +393,9 @@ Store a string representation of a rule in the DB. exports.storeRule = ( ruleId, data ) => @log.info "DB | storeRule: '#{ ruleId }'" @db.sadd 'rules', "#{ ruleId }", - replyHandler "storing rule key '#{ ruleId }'" + replyHandler "sadd rules: '#{ ruleId }'" @db.set "rule:#{ ruleId }", data, - replyHandler "storing rule '#{ ruleId }'" + replyHandler "set 'rule:#{ ruleId }': data" ### Delete a string representation of a rule. @@ -406,24 +406,25 @@ Delete a string representation of a rule. ### exports.deleteRule = ( ruleId ) => @log.info "DB | deleteRule: '#{ ruleId }'" - @db.srem "rules", ruleId, replyHandler "Deleting rule key '#{ ruleId }'" - @db.del "rule:#{ ruleId }", replyHandler "Deleting rule '#{ ruleId }'" + @db.srem "rules", ruleId, replyHandler "srem 'rules': '#{ ruleId }'" + @db.del "rule:#{ ruleId }", replyHandler "del: 'rule:#{ ruleId }'" # We also need to delete all references in linked and active users @db.smembers "rule:#{ ruleId }:users", ( err, obj ) => delLinkedUserRule = ( userId ) => + exports.resetLog userId, ruleId @db.srem "user:#{ userId }:rules", ruleId, - replyHandler "Deleting rule key '#{ ruleId }' in linked user '#{ userId }'" + replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" delLinkedUserRule id for id in obj - @db.del "rule:#{ ruleId }:users", replyHandler "Deleting rule '#{ ruleId }' users" + @db.del "rule:#{ ruleId }:users", replyHandler "del 'rule:#{ ruleId }:users'" @db.smembers "rule:#{ ruleId }:active-users", ( err, obj ) => delActiveUserRule = ( userId ) => @db.srem "user:#{ userId }:active-rules", ruleId, - replyHandler "Deleting rule key '#{ ruleId }' in active user '#{ userId }'" + replyHandler "srem 'user:#{ userId }:active-rules': '#{ ruleId }'" delActiveUserRule id for id in obj - @db.del "rule:#{ ruleId }:active-users", - replyHandler "Deleting rule '#{ ruleId }' active users" + @db.del "rule:#{ ruleId }:active-users", + replyHandler "del 'rule:#{ ruleId }:active-users'" ### Associate a rule to a user. @@ -433,11 +434,11 @@ Associate a rule to a user. @param {String} userId ### exports.linkRule = ( ruleId, userId ) => - @log.info "DB | linkRule: '#{ ruleId }' for user '#{ userId }'" + @log.info "DB | linkRule: '#{ ruleId }' to user '#{ userId }'" @db.sadd "rule:#{ ruleId }:users", userId, - replyHandler "storing user '#{ userId }' for rule key '#{ ruleId }'" + replyHandler "sadd 'rule:#{ ruleId }:users': '#{ userId }'" @db.sadd "user:#{ userId }:rules", ruleId, - replyHandler "storing rule key '#{ ruleId }' for user '#{ userId }'" + replyHandler "sadd 'user:#{ userId }:rules': '#{ ruleId }'" ### Get rules linked to a user and hand it to cb(err, obj). @@ -447,7 +448,7 @@ Get rules linked to a user and hand it to cb(err, obj). @param {function} cb ### exports.getUserLinkedRules = ( userId, cb ) => - @log.info "DB | getUserLinkedRules: for user '#{ userId }'" + @log.info "DB | getUserLinkedRules: 'user:#{ userId }:rules'" @db.smembers "user:#{ userId }:rules", cb ### @@ -458,7 +459,7 @@ Get users linked to a rule and hand it to cb(err, obj). @param {function} cb ### exports.getRuleLinkedUsers = ( ruleId, cb ) => - @log.info "DB | getRuleLinkedUsers: for rule '#{ ruleId }'" + @log.info "DB | getRuleLinkedUsers: 'rule:#{ ruleId }:users'" @db.smembers "rule:#{ ruleId }:users", cb ### @@ -471,9 +472,9 @@ Delete an association of a rule to a user. exports.unlinkRule = ( ruleId, userId ) => @log.info "DB | unlinkRule: '#{ ruleId }:#{ userId }'" @db.srem "rule:#{ ruleId }:users", userId, - replyHandler "removing user '#{ userId }' for rule key '#{ ruleId }'" + replyHandler "srem 'rule:#{ ruleId }:users': '#{ userId }'" @db.srem "user:#{ userId }:rules", ruleId, - replyHandler "removing rule key '#{ ruleId }' for user '#{ userId }'" + replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" ### Activate a rule. @@ -485,9 +486,9 @@ Activate a rule. exports.activateRule = ( ruleId, userId ) => @log.info "DB | activateRule: '#{ ruleId }' for '#{ userId }'" @db.sadd "rule:#{ ruleId }:active-users", userId, - replyHandler "storing activated user '#{ userId }' in rule '#{ ruleId }'" + replyHandler "sadd 'rule:#{ ruleId }:active-users': '#{ userId }'" @db.sadd "user:#{ userId }:active-rules", ruleId, - replyHandler "storing activated rule '#{ ruleId }' in user '#{ userId }'" + replyHandler "sadd 'user:#{ userId }:active-rules': '#{ ruleId }'" ### Get rules activated for a user and hand it to cb(err, obj). @@ -497,7 +498,7 @@ Get rules activated for a user and hand it to cb(err, obj). @param {function} cb ### exports.getUserActivatedRules = ( userId, cb ) => - @log.info "DB | getUserActivatedRules: for user '#{ userId }'" + @log.info "DB | getUserActivatedRules: smembers 'user:#{ userId }:active-rules'" @db.smembers "user:#{ userId }:active-rules", cb ### @@ -508,7 +509,7 @@ Get users activated for a rule and hand it to cb(err, obj). @param {function} cb ### exports.getRuleActivatedUsers = ( ruleId, cb ) => - @log.info "DB | getRuleActivatedUsers: for rule '#{ ruleId }'" + @log.info "DB | getRuleActivatedUsers: smembers 'rule:#{ ruleId }:active-users'" @db.smembers "rule:#{ ruleId }:active-users", cb ### @@ -521,9 +522,9 @@ Deactivate a rule. exports.deactivateRule = ( ruleId, userId ) => @log.info "DB | deactivateRule: '#{ ruleId }' for '#{ userId }'" @db.srem "rule:#{ ruleId }:active-users", userId, - replyHandler "removing activated user '#{ userId }' in rule '#{ ruleId }'" + replyHandler "srem 'rule:#{ ruleId }:active-users': '#{ userId }'" @db.srem "user:#{ userId }:active-rules", ruleId, - replyHandler "removing activated rule '#{ ruleId }' in user '#{ userId }'" + replyHandler "srem 'user:#{ userId }:active-rules' '#{ ruleId }'" ### Fetch all active ruleIds and pass them to cb(err, obj). diff --git a/coffee/request-handler.coffee b/coffee/request-handler.coffee index 1f65253..48e6986 100644 --- a/coffee/request-handler.coffee +++ b/coffee/request-handler.coffee @@ -49,7 +49,7 @@ exports = module.exports = ( args ) => fStoreUser = ( username, oUser ) -> oUser.username = username db.storeUser oUser - fStoreUser user, users[user] for user of users + fStoreUser user, oUser for user, oUser of users module.exports @@ -104,7 +104,7 @@ exports.handleLogin = ( req, resp ) => body = '' req.on 'data', ( data ) -> body += data req.on 'end', => - obj = qs.parse body + obj = JSON.parse body db.loginUser obj.username, obj.password, ( err, usr ) => if err # Tapping on fingers, at least in log... diff --git a/config/users.json b/config/users.json index 5c8a5af..12616d9 100644 --- a/config/users.json +++ b/config/users.json @@ -2,5 +2,9 @@ "admin": { "password": "7407946a7a90b037ba5e825040f184a142161e4c61d81feb83ec8c7f011a99b0d77f39c9170c3231e1003c5cf859c69bd93043b095feff5cce6f6d45ec513764", "roles": [ "admin" ] + }, + "dominic": { + "password": "2d51496fbe5b6d3e98e22d68140609eaedd64de457b2f75c346a4a98f87928eac11ea2be747709ae7a2f5b177af09a60a8dbf14bf703e0cb9b147fc0a3e3a064", + "roles": [ "admin" ] } } diff --git a/examples/action-invokers/emailyak.coffee b/examples/action-invokers/emailyak.coffee new file mode 100644 index 0000000..0961c3d --- /dev/null +++ b/examples/action-invokers/emailyak.coffee @@ -0,0 +1,41 @@ +### +EmailYak ACTION INVOKER +------------------------ +# +# Requires user params: +# - apikey: The user's EmailYak API key +# - sender: The email address belonging to your apikey +# - receipient: The email address for the one that receives the mail +# - subject: The subject of the mail +### + +url = 'https://api.emailyak.com/v1/' + params.apikey + '/json/send/email/' + +# +# The standard callback can be used if callback is not provided, e.g. if +# the function is called from outside +# +standardCallback = ( funcName ) -> + ( err, resp, body ) -> + if err + log "ERROR: During function '#{ funcName }'" + else + if resp.statusCode is 200 + log "Function '#{ funcName }' ran through without error" + else + debug body + log "ERROR: During function '#{ funcName }': #{ body.error.message }" + +### +Send a mail through Emailyak. + +@param {Object} args.content the content to be posted in the mail body +### +exports.sendMail = ( args ) -> + data = + FromAddress: params.sender + ToAddress: params.receipient + Subject: params.subject + TextBody: args.content + needlereq 'post', url, data, json: true, standardCallback 'sendMail' + diff --git a/examples/action-invokers/probinder.coffee b/examples/action-invokers/probinder.coffee index a6d5a30..06c9446 100644 --- a/examples/action-invokers/probinder.coffee +++ b/examples/action-invokers/probinder.coffee @@ -1,4 +1,3 @@ - ### ProBinder ACTION INVOKER ------------------------ @@ -38,7 +37,7 @@ Call the ProBinder service with the given parameters. @param {String} args.method the required method identifier to be appended to the url @param {function} [args.callback] the function to receive the request answer ### -exports.call = ( args ) -> +callService = ( args ) -> if not args.service or not args.method log 'ERROR in call function: Missing arguments!' else @@ -47,41 +46,6 @@ exports.call = ( args ) -> url = urlService + args.service + '/' + args.method needlereq 'post', url, args.data, credentials, args.callback -### -Calls the user's unread content service. - -@param {Object} [args] the optional object containing the callback function -@param {function} [args.callback] refer to call function -### -exports.getUnreadContents = ( args ) -> - if not args.callback - args.callback = standardCallback 'getUnreadContents' - exports.call - service: '36' - method: 'unreadcontent' - callback: args.callback - - -### -Calls the content get service with the content id and the service id provided. - -@param {Object} args the object containing the service id and the content id, - success and error callback methods -@param {String} args.serviceid the service id that is able to process this content -@param {String} args.contentid the content id -@param {function} [args.callback] receives the needle answer from the "call" function -### -exports.getContent = ( args ) -> - if not args.callback - args.callback = standardCallback 'getContent' - exports.call - service: '2' - method: 'get' - data: - id: args.contentid - service: args.serviceid - callback: args.callback - ### Does everything to post something in a binder @@ -92,7 +56,7 @@ Does everything to post something in a binder exports.newContent = ( args ) -> if not args.callback args.callback = standardCallback 'newContent' - exports.call + callService service: '27' method: 'save' data: @@ -111,11 +75,11 @@ Does everything to post a file info in a binder tabe exports.makeFileEntry = ( args ) -> if not args.callback args.callback = standardCallback 'makeFileEntry' - exports.getContent + getContent serviceid: args.service contentid: args.id callback: ( err, resp, body ) -> - exports.call + callService service: '27' method: 'save' data: @@ -125,6 +89,26 @@ exports.makeFileEntry = ( args ) -> find it here!'" callback: args.callback +### +Calls the content get service with the content id and the service id provided. + +@param {Object} args the object containing the service id and the content id, + success and error callback methods +@param {String} args.serviceid the service id that is able to process this content +@param {String} args.contentid the content id +@param {function} [args.callback] receives the needle answer from the "call" function +### +getContent = ( args ) -> + if not args.callback + args.callback = standardCallback 'getContent' + callService + service: '2' + method: 'get' + data: + id: args.contentid + service: args.serviceid + callback: args.callback + ### Sets the content as read. @@ -134,7 +118,7 @@ Sets the content as read. exports.setRead = ( args ) -> if not args.callback args.callback = standardCallback 'setRead' - exports.call + callService service: '2' method: 'setread' data: diff --git a/examples/action-invokers/remote-engine.coffee b/examples/action-invokers/remote-engine.coffee new file mode 100644 index 0000000..a79d329 --- /dev/null +++ b/examples/action-invokers/remote-engine.coffee @@ -0,0 +1,49 @@ +### +Remote Engine +------------- +# +# Requires user params: +# - username: username to the remote system +# - password: password to the remote system +# - event: The event type to be pushed into the system +# - url: The url to the WebAPI engine that will receive the event +### +hashedPassword = cryptoJS.SHA3( params.password, outputLength: 512 ).toString() +options = + method: 'POST' + json: true + jar: true + +fPushEvent = ( evt ) -> + options.url = params.url + '/event' + options.body = JSON.stringify evt + request options, ( err, resp, body ) -> + if err or resp.statusCode isnt 200 + log 'Error in pushing event!' + else + log 'Successfully posted an event' + + +### +Push an event into a WebAPI engine. + +@param {Object} evt The event object that will be transmitted. +### +exports.pushEvent = ( evt ) -> + if not evt + evt = {} + evt.event = params.event + + data = + username: params.username + password: hashedPassword + options.url = params.url + '/login' + options.body = JSON.stringify data + request options, ( err, resp, body ) -> + if err or resp.statusCode isnt 200 + log 'Error in pushing event!' + else + fPushEvent evt + + +# http://localhost:8125 \ No newline at end of file diff --git a/mod_actions/wikipedia/wikipedia.js b/examples/action-invokers/wikipedia.js similarity index 100% rename from mod_actions/wikipedia/wikipedia.js rename to examples/action-invokers/wikipedia.js diff --git a/examples/action-invokers/continuously.coffee b/examples/event-pollers/continuously.coffee similarity index 100% rename from examples/action-invokers/continuously.coffee rename to examples/event-pollers/continuously.coffee diff --git a/examples/event-pollers/emailyak.coffee b/examples/event-pollers/emailyak.coffee index 313fad6..9b45b5d 100644 --- a/examples/event-pollers/emailyak.coffee +++ b/examples/event-pollers/emailyak.coffee @@ -16,11 +16,11 @@ exports.newMail = ( pushEvent ) -> # # Syntax: needle.request method, url, data, [options], callback # - needlereq 'get', url, null, null, ( err, resp, body ) -> - if err - log 'Error in EmailYak EM newMail: ' + err.message - else - if resp.statusCode is 200 - mails = JSON.parse( body ).Emails - pushEvent mail for mail in mails + needlereq 'get', url, null, null, ( err, resp, body ) -> + if err + log 'Error in EmailYak EM newMail: ' + err.message + else + log body + if resp.statusCode is 200 + pushEvent mail for mail in body.Emails diff --git a/examples/event-pollers/probinder.coffee b/examples/event-pollers/probinder.coffee new file mode 100644 index 0000000..3d65b6f --- /dev/null +++ b/examples/event-pollers/probinder.coffee @@ -0,0 +1,91 @@ +### +ProBinder EVENT POLLER +---------------------- + +Global variables +This module requires user-specific parameters: +- username +- password +### +urlService = 'https://probinder.com/service/' +credentials = + username: params.username + password: params.password + +# +# The standard callback can be used if callback is not provided, e.g. if +# the function is called from outside +# +standardCallback = ( funcName ) -> + ( err, resp, body ) -> + if err + log "ERROR: During function '#{ funcName }'" + else + if resp.statusCode is 200 + log "Function '#{ funcName }' ran through without error" + else + log "ERROR: During function '#{ funcName }': #{ body.error.message }" + +### +Call the ProBinder service with the given parameters. + +@param {Object} args the required function arguments object +@param {Object} [args.data] the data to be posted +@param {String} args.service the required service identifier to be appended to the url +@param {String} args.method the required method identifier to be appended to the url +@param {function} [args.callback] the function to receive the request answer +### +callService = ( args ) -> + if not args.service or not args.method + log 'ERROR in call function: Missing arguments!' + else + if not args.callback + args.callback = standardCallback 'call' + url = urlService + args.service + '/' + args.method + needlereq 'post', url, args.data, credentials, args.callback + +### +Calls the user's unread content service. +### +exports.unreadContentInfo = ( pushEvent ) -> + callService + service: '36' + method: 'unreadcontent' + callback: ( err, resp, body ) -> + if not err and resp.statusCode is 200 + pushEvent oEntry for oEntry in body + else + log 'Error: ' + body.error.message + +### +Fetches unread contents +### +exports.unreadContent = ( pushEvent ) -> + exports.unreadContentInfo ( evt ) -> + getContent + contentId: evt.id + contentServiceId: evt.serviceId + callback: ( err, resp, body ) -> + if not err and resp.statusCode is 200 + pushEvent + id: body.id + content: body.text + object: body + else + log 'Error: ' + body.error.message + + +### +Calls the content get service with the content id and the service id provided. +### +getContent = ( args ) -> + if not args.callback + args.callback = standardCallback 'getContent' + callService + service: '2' + method: 'get' + data: + id: args.contentId + service: args.contentServiceId + callback: args.callback + diff --git a/examples/event-pollers/system.coffee b/examples/event-pollers/system.coffee new file mode 100644 index 0000000..b8d021e --- /dev/null +++ b/examples/event-pollers/system.coffee @@ -0,0 +1,16 @@ +### +System information +------------------------ +### + +isRunning = false + +### +This event is emitted if the system had a restart. +### +exports.hasRestarted = ( pushEvent ) -> + if not isRunning + isRunning = true + pushEvent + content: "The system has been restarted at #{ ( new Date ).toISOString() }" + diff --git a/examples/event-pollers/weather.coffee b/examples/event-pollers/weather.coffee new file mode 100644 index 0000000..14e1110 --- /dev/null +++ b/examples/event-pollers/weather.coffee @@ -0,0 +1,61 @@ +### +OpenWeather EVENT POLLER +------------------------ + +This module requires user-specific parameters: +- openweatherKey +- tempThreshold +- city +- eventTime ( hh:mm of the day ) +### +urlService = 'http://api.openweathermap.org/data/2.5/weather' +lastEvent = new Date 0 +twentyFourHoursInms = 24 * 60 * 60 * 1000 +dayTimeInMin = 0 + +calcEventDayTimeInMin = ( et ) -> + arrTime = et.split ':' + hrs = parseInt arrTime[ 0 ] + mins = parseInt arrTime[ 1 ] + dayTimeInMin = hrs * 60 + mins + if isNaN dayTimeInMin + log 'Wrong temperature input! ' + et + +try + calcEventDayTimeInMin params.eventTime +catch err + log 'Unable to parse the eventTime parameter' + + +### +Fetches the temperature +### +getTemperature = ( cb ) -> + url = urlService + '?APPID=' + params.openweatherKey + '&q=' + params.city + needlereq 'get', url, null, null, cb + +### +Emits one event per day if the temperature today raises above user defined threshold +### +exports.temperatureOverThreshold = ( pushEvent ) -> + getTemperature ( err, resp, body ) -> + timeNow = new Date() + + if err or resp.statusCode isnt 200 + debug body + else + #If temperature is above threshold + if body.main.temp_max - 272.15 > params.tempThreshold and + + # If last event was more than 24 hours ago + timeNow - lastEvent > twentyFourHoursInms and + + # If we are past the time the user wants to get the information + timeNow.getHours() * 60 + timeNow.getMinutes() > dayTimeInMin + + lastEvent = timeNow + pushEvent + threshold: params.tempThreshold + measured: body.main.temp_max - 272.15 + content: "The temperature will be #{ body.main.temp_max - 272.15 } today!" + diff --git a/examples/runscript.coffee b/examples/runscript.coffee index fed190f..daaff56 100644 --- a/examples/runscript.coffee +++ b/examples/runscript.coffee @@ -15,23 +15,51 @@ if not process.argv[ 2 ] fs = require 'fs' vm = require 'vm' cs = require 'coffee-script' +needle = require 'needle' +crypto = require 'crypto-js' +request = require 'request' issueApiCall = ( method, url, data, options, cb ) -> - cb new Error 'not possible' + try + needle.request method, url, data, options, ( err, resp, body ) => + try + cb err, resp, body + catch err + console.log 'Error during needle request! ' + err.message + catch err + console.log 'Error before needle request! ' + err.message -params = {} -data = fs.readFileSync process.argv[ 2 ], 'utf8' -src = cs.compile data +issueRequest = ( options, cb ) -> + try + request options, ( err, resp, body ) => + try + cb err, resp, body + catch err + console.log 'Error during request! ' + err.message + catch err + console.log 'Error before request! ' + err.message + +params = JSON.parse fs.readFileSync 'params.json', 'utf8' +code = fs.readFileSync process.argv[ 2 ], 'utf8' +src = cs.compile code sandbox = id: 'test.vm' - params: params + params: params.userparams needlereq: issueApiCall + request: issueRequest + cryptoJS: crypto log: console.log debug: console.log exports: {} vm.runInNewContext src, sandbox, sandbox.id +if process.argv[ 3 ] is 'ep' + sandbox.exports[ process.argv[ 4 ] ] ( evt ) -> + console.log evt +else + sandbox.exports[ process.argv[ 3 ] ] params.event + console.log "If no error happened until here it seems the script compiled and ran correctly! Congrats!" \ No newline at end of file diff --git a/examples/runscript.js b/examples/runscript.js index d31dc56..aaa559f 100644 --- a/examples/runscript.js +++ b/examples/runscript.js @@ -1,6 +1,15 @@ // Generated by CoffeeScript 1.7.1 + +/* +runscript.js +------------ + +A script that helps to track errors happening durin coffee +compilation and running of module code + */ + (function() { - var cs, data, fs, issueApiCall, params, sandbox, src, vm; + var code, crypto, cs, fs, issueApiCall, issueRequest, needle, params, request, sandbox, src, vm; if (!process.argv[2]) { console.log('Please provide a path to a coffee file'); @@ -13,20 +22,62 @@ cs = require('coffee-script'); + needle = require('needle'); + + crypto = require('crypto-js'); + + request = require('request'); + issueApiCall = function(method, url, data, options, cb) { - return cb(new Error('not possible')); + var err; + try { + return needle.request(method, url, data, options, (function(_this) { + return function(err, resp, body) { + try { + return cb(err, resp, body); + } catch (_error) { + err = _error; + return console.log('Error during needle request! ' + err.message); + } + }; + })(this)); + } catch (_error) { + err = _error; + return console.log('Error before needle request! ' + err.message); + } }; - params = {}; + issueRequest = function(options, cb) { + var err; + try { + return request(options, (function(_this) { + return function(err, resp, body) { + try { + return cb(err, resp, body); + } catch (_error) { + err = _error; + return console.log('Error during request! ' + err.message); + } + }; + })(this)); + } catch (_error) { + err = _error; + return console.log('Error before request! ' + err.message); + } + }; - data = fs.readFileSync(process.argv[2], 'utf8'); + params = JSON.parse(fs.readFileSync('params.json', 'utf8')); - src = cs.compile(data); + code = fs.readFileSync(process.argv[2], 'utf8'); + + src = cs.compile(code); sandbox = { id: 'test.vm', - params: params, + params: params.userparams, needlereq: issueApiCall, + request: issueRequest, + cryptoJS: crypto, log: console.log, debug: console.log, exports: {} @@ -34,6 +85,14 @@ vm.runInNewContext(src, sandbox, sandbox.id); - console.log('If no error happened until here it seems the script compiled and ran correctly! Congrats!'); + if (process.argv[3] === 'ep') { + sandbox.exports[process.argv[4]](function(evt) { + return console.log(evt); + }); + } else { + sandbox.exports[process.argv[3]](params.event); + } + + console.log("If no error happened until here it seems the script compiled and ran correctly! Congrats!"); }).call(this); diff --git a/js/dynamic-modules.js b/js/dynamic-modules.js index 4ec929b..63f1f7e 100644 --- a/js/dynamic-modules.js +++ b/js/dynamic-modules.js @@ -9,7 +9,7 @@ Dynamic Modules */ (function() { - var cryptico, cs, db, exports, issueApiCall, logFunction, needle, vm; + var cryptico, cryptoJS, cs, db, exports, issueNeedleCall, issueRequest, logFunction, needle, request, vm; db = require('./persistence'); @@ -17,10 +17,14 @@ Dynamic Modules needle = require('needle'); + request = require('request'); + cs = require('coffee-script'); cryptico = require('my-cryptico'); + cryptoJS = require('crypto-js'); + /* Module call @@ -52,7 +56,7 @@ Dynamic Modules }; })(this); - issueApiCall = function(logger) { + issueNeedleCall = function(logger) { return function(method, url, data, options, cb) { var err; try { @@ -73,6 +77,27 @@ Dynamic Modules }; }; + issueRequest = function(logger) { + return function(options, cb) { + var err; + try { + return request(options, (function(_this) { + return function(err, resp, body) { + try { + return cb(err, resp, body); + } catch (_error) { + err = _error; + return logger('Error during request! ' + err.message); + } + }; + })(this)); + } catch (_error) { + err = _error; + return logger('Error before request! ' + err.message); + } + }; + }; + logFunction = function(uId, rId, mId) { return function(msg) { return db.appendLog(uId, rId, mId, msg); @@ -127,7 +152,9 @@ Dynamic Modules sandbox = { id: userId + '.' + modId + '.vm', params: params, - needlereq: issueApiCall(logFunc), + needlereq: issueNeedleCall(logFunc), + request: issueRequest(logFunc), + cryptoJS: cryptoJS, log: logFunc, debug: console.log, exports: {} diff --git a/js/persistence.js b/js/persistence.js index 22d1d58..4420bf2 100644 --- a/js/persistence.js +++ b/js/persistence.js @@ -415,7 +415,7 @@ Persistence exports.appendLog = (function(_this) { return function(userId, ruleId, moduleId, message) { - return _this.db.append("" + userId + ":" + ruleId, "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n"); + return _this.db.append("" + userId + ":" + ruleId + ":log", "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n"); }; })(this); @@ -431,7 +431,7 @@ Persistence exports.getLog = (function(_this) { return function(userId, ruleId, cb) { - return _this.db.get("" + userId + ":" + ruleId, cb); + return _this.db.get("" + userId + ":" + ruleId + ":log", cb); }; })(this); @@ -446,7 +446,7 @@ Persistence exports.resetLog = (function(_this) { return function(userId, ruleId) { - return _this.db.del("" + userId + ":" + ruleId, replyHandler("RESET LOG '" + userId + ":" + ruleId + "'")); + return _this.db.del("" + userId + ":" + ruleId + ":log", replyHandler("del '" + userId + ":" + ruleId + ":log'")); }; })(this); @@ -461,7 +461,7 @@ Persistence exports.getRule = (function(_this) { return function(ruleId, cb) { - _this.log.info("DB | getRule: '" + ruleId + "'"); + _this.log.info("DB | get: 'rule:" + ruleId + "'"); return _this.db.get("rule:" + ruleId, cb); }; })(this); @@ -476,7 +476,7 @@ Persistence exports.getRules = (function(_this) { return function(cb) { - _this.log.info('DB | Fetching all Rules'); + _this.log.info("DB | Fetching all Rules: getSetRecords 'rules'"); return getSetRecords('rules', exports.getRule, cb); }; })(this); @@ -491,7 +491,7 @@ Persistence exports.getRuleIds = (function(_this) { return function(cb) { - _this.log.info('DB | Fetching all Rule IDs'); + _this.log.info("DB | Fetching all Rule IDs: 'rules'"); return _this.db.smembers('rules', cb); }; })(this); @@ -508,8 +508,8 @@ Persistence exports.storeRule = (function(_this) { return function(ruleId, data) { _this.log.info("DB | storeRule: '" + ruleId + "'"); - _this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'")); - return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'")); + _this.db.sadd('rules', "" + ruleId, replyHandler("sadd rules: '" + ruleId + "'")); + return _this.db.set("rule:" + ruleId, data, replyHandler("set 'rule:" + ruleId + "': data")); }; })(this); @@ -525,12 +525,13 @@ Persistence exports.deleteRule = (function(_this) { return function(ruleId) { _this.log.info("DB | deleteRule: '" + ruleId + "'"); - _this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'")); - _this.db.del("rule:" + ruleId, replyHandler("Deleting rule '" + ruleId + "'")); + _this.db.srem("rules", ruleId, replyHandler("srem 'rules': '" + ruleId + "'")); + _this.db.del("rule:" + ruleId, replyHandler("del: 'rule:" + ruleId + "'")); _this.db.smembers("rule:" + ruleId + ":users", function(err, obj) { var delLinkedUserRule, id, _i, _len, _results; delLinkedUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in linked user '" + userId + "'")); + exports.resetLog(userId, ruleId); + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("srem 'user:" + userId + ":rules': '" + ruleId + "'")); }; _results = []; for (_i = 0, _len = obj.length; _i < _len; _i++) { @@ -539,11 +540,11 @@ Persistence } return _results; }); - _this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting rule '" + ruleId + "' users")); + _this.db.del("rule:" + ruleId + ":users", replyHandler("del 'rule:" + ruleId + ":users'")); _this.db.smembers("rule:" + ruleId + ":active-users", function(err, obj) { var delActiveUserRule, id, _i, _len, _results; delActiveUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in active user '" + userId + "'")); + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("srem 'user:" + userId + ":active-rules': '" + ruleId + "'")); }; _results = []; for (_i = 0, _len = obj.length; _i < _len; _i++) { @@ -552,7 +553,7 @@ Persistence } return _results; }); - return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users")); + return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("del 'rule:" + ruleId + ":active-users'")); }; })(this); @@ -567,9 +568,9 @@ Persistence exports.linkRule = (function(_this) { return function(ruleId, userId) { - _this.log.info("DB | linkRule: '" + ruleId + "' for user '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("storing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("storing rule key '" + ruleId + "' for user '" + userId + "'")); + _this.log.info("DB | linkRule: '" + ruleId + "' to user '" + userId + "'"); + _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("sadd 'rule:" + ruleId + ":users': '" + userId + "'")); + return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("sadd 'user:" + userId + ":rules': '" + ruleId + "'")); }; })(this); @@ -584,7 +585,7 @@ Persistence exports.getUserLinkedRules = (function(_this) { return function(userId, cb) { - _this.log.info("DB | getUserLinkedRules: for user '" + userId + "'"); + _this.log.info("DB | getUserLinkedRules: 'user:" + userId + ":rules'"); return _this.db.smembers("user:" + userId + ":rules", cb); }; })(this); @@ -600,7 +601,7 @@ Persistence exports.getRuleLinkedUsers = (function(_this) { return function(ruleId, cb) { - _this.log.info("DB | getRuleLinkedUsers: for rule '" + ruleId + "'"); + _this.log.info("DB | getRuleLinkedUsers: 'rule:" + ruleId + ":users'"); return _this.db.smembers("rule:" + ruleId + ":users", cb); }; })(this); @@ -617,8 +618,8 @@ Persistence exports.unlinkRule = (function(_this) { return function(ruleId, userId) { _this.log.info("DB | unlinkRule: '" + ruleId + ":" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("removing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("removing rule key '" + ruleId + "' for user '" + userId + "'")); + _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("srem 'rule:" + ruleId + ":users': '" + userId + "'")); + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("srem 'user:" + userId + ":rules': '" + ruleId + "'")); }; })(this); @@ -634,8 +635,8 @@ Persistence exports.activateRule = (function(_this) { return function(ruleId, userId) { _this.log.info("DB | activateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("storing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("storing activated rule '" + ruleId + "' in user '" + userId + "'")); + _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("sadd 'rule:" + ruleId + ":active-users': '" + userId + "'")); + return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("sadd 'user:" + userId + ":active-rules': '" + ruleId + "'")); }; })(this); @@ -650,7 +651,7 @@ Persistence exports.getUserActivatedRules = (function(_this) { return function(userId, cb) { - _this.log.info("DB | getUserActivatedRules: for user '" + userId + "'"); + _this.log.info("DB | getUserActivatedRules: smembers 'user:" + userId + ":active-rules'"); return _this.db.smembers("user:" + userId + ":active-rules", cb); }; })(this); @@ -666,7 +667,7 @@ Persistence exports.getRuleActivatedUsers = (function(_this) { return function(ruleId, cb) { - _this.log.info("DB | getRuleActivatedUsers: for rule '" + ruleId + "'"); + _this.log.info("DB | getRuleActivatedUsers: smembers 'rule:" + ruleId + ":active-users'"); return _this.db.smembers("rule:" + ruleId + ":active-users", cb); }; })(this); @@ -683,8 +684,8 @@ Persistence exports.deactivateRule = (function(_this) { return function(ruleId, userId) { _this.log.info("DB | deactivateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("removing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("removing activated rule '" + ruleId + "' in user '" + userId + "'")); + _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("srem 'rule:" + ruleId + ":active-users': '" + userId + "'")); + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("srem 'user:" + userId + ":active-rules' '" + ruleId + "'")); }; })(this); diff --git a/js/request-handler.js b/js/request-handler.js index 212cdc0..4011f31 100644 --- a/js/request-handler.js +++ b/js/request-handler.js @@ -29,7 +29,7 @@ Request Handler exports = module.exports = (function(_this) { return function(args) { - var fStoreUser, user, users; + var fStoreUser, oUser, user, users; _this.log = args.logger; _this.userRequestHandler = args['request-service']; _this.objAdminCmds = { @@ -50,7 +50,8 @@ Request Handler return db.storeUser(oUser); }; for (user in users) { - fStoreUser(user, users[user]); + oUser = users[user]; + fStoreUser(user, oUser); } return module.exports; }; @@ -124,7 +125,7 @@ Request Handler }); return req.on('end', function() { var obj; - obj = qs.parse(body); + obj = JSON.parse(body); return db.loginUser(obj.username, obj.password, function(err, usr) { if (err) { _this.log.warn("RH | AUTH-UH-OH ( " + obj.username + " ): " + err.message); diff --git a/mod_actions/probinder/probinder.js b/mod_actions/probinder/probinder.js deleted file mode 100644 index 995e77c..0000000 --- a/mod_actions/probinder/probinder.js +++ /dev/null @@ -1,188 +0,0 @@ -'use strict'; - -/** - * ProBinder ACTION MODULE - */ - -var urlService = 'https://probinder.com/service/', - credentials = null; - -exports.validUserParams = function() { - -} - -function loadCredentials(cred) { - if(!cred || !cred.username || !cred.password) { - console.error('ERROR: ProBinder AM credentials file corrupt'); - } else { - credentials = cred; - console.log('Successfully loaded credentials for ProBinder AM'); - } -} - -/** - * Reset eventually loaded credentials - */ -function purgeCredentials() { - credentials = null; -}; - -/** - * Verify whether the arguments match the existing credentials. - * @param {String} username the username - * @param {String} password the password - */ -function verifyCredentials(username, password) { - if(!credentials) return false; - return credentials.username === username - && credentials.password === password; -}; - -/** - * Call the ProBinder service with the given parameters. - * @param {Object} args the required function arguments object - * @param {Object} [args.data] the data to be posted - * @param {String} args.service the required service identifier to be appended to the url - * @param {String} args.method the required method identifier to be appended to the url - * @param {function} [args.succes] the function to be called on success, - * receives the response body String or Buffer. - * @param {function} [args.error] the function to be called on error, - * receives an error, an http.ClientResponse object and a response body - * String or Buffer. - */ -function call(args) { - if(!args || !args.service || !args.method) { - console.error('ERROR in ProBinder AM call: Too few arguments!'); - return null; - } - if(credentials){ - needle.post(urlService + args.service + '/' + args.method, - args.data, - credentials, - function(error, response, body) { // The callback - if(!error && response && response.statusCode == 200) { - if(args && args.success) args.success(body); - } else { - if(args && args.error) args.error(error, response, body); - else console.error('Error during ProBinder AM call: ' + error.message); - } - } - ); - } else console.error('ERROR ProBinder AM: request or credentials object not ready!'); -}; - -/** - * Calls the user's unread content service. - * @param {Object} [args] the optional object containing the success - * and error callback methods - * @param {function} [args.succes] refer to call function - * @param {function} [args.error] refer to call function - */ -function getUnreadContents(args) { - if(!args) args = {}; - call({ - service: '36', - method: 'unreadcontent', - success: args.success, - error: args.error - }); -}; - -/** - * Calls the content get service with the content id and the service id provided. - * @param {Object} args the object containing the service id and the content id, - * success and error callback methods - * @param {String} args.serviceid the service id that is able to process this content - * @param {String} args.contentid the content id - * @param {function} [args.succes] to be called on success, receives the service, content - * and user id's along with the content - * @param {function} [args.error] refer to call function - */ -function getContent(args){ - if(!args || !args.serviceid || !args.contentid) { - console.error('ERROR in ProBinder AM getContent: Too few arguments!'); - return null; - } - call({ - service: '2', - method: 'get', - data: { id: args.contentid, service: args.serviceid }, - success: args.success, - error: args.error - }); -} - -/** - * Does everything to post something in a binder - * @param {Object} args the object containing the content - * @param {String} args.content the content to be posted - */ -function newContent(args){ - if(!args) args = {}; - if(!args.content) args.content = 'Rule#0 says you received a new mail!'; - call({ - service: '27', - method: 'save', - data: { - companyId: '961', - context: '17936', - text: args.content - } - }); -} - -/** - * Does everything to post a file info in a binder tabe - * @param {Object} args the object containing the content - * @param {String} args.service the content service - * @param {String} args.id the content id - */ -function makeFileEntry(args){ - if(!args || !args.service || !args.id) { - console.error('ERROR in ProBinder AM makeFileEntry: Too few arguments!'); - return null; - } - getContent({ - serviceid: args.service, - contentid: args.id, - success: function(data) { - call({ - service: '27', - method: 'save', - data: { - companyId: '961', - context: '17936', - text: 'New file (' + data.title + ') in tab \"' + data.context[0].name - + '\", find it here!' - } - }); - } - }); -} - -/** - * Does everything to post something in a binder - * @param {Object} args the object containing the content - * @param {String} args.content the content to be posted - */ -function setRead(args){ - call({ - service: '2', - method: 'setread', - data: { - id: args.id - } - }); -} - -exports.loadCredentials = loadCredentials; -exports.purgeCredentials = purgeCredentials; -exports.verifyCredentials = verifyCredentials; -exports.call = call; -exports.getUnreadContents = getUnreadContents; -// exports.getBinderTabContents = getBinderTabContents; -exports.getContent = getContent; -exports.newContent = newContent; -exports.makeFileEntry = makeFileEntry; -exports.setRead = setRead; - diff --git a/mod_actions/testing/testing.js b/mod_actions/testing/testing.js deleted file mode 100644 index 076313d..0000000 --- a/mod_actions/testing/testing.js +++ /dev/null @@ -1,18 +0,0 @@ -log.print('TT', 'action testing.js'); -log.obj('exports', exports); -log.obj('this', this); -/* -// Hacking my own system... - console.log(module.parent.parent.children[0].exports.getEventModuleAuth('probinder', - function(err, obj) {console.log(obj);})); -*/ - -//FIXME do not try to delete a file and rely on it to exist, rather try to create it first! o check for its existance and then delete it -try { - fs.unlinkSync(path.resolve(__dirname, 'event_modules', 'malicious', 'test.json')); - log.error('VERY BAD! NEVER START THIS SERVER WITH A USER THAT HAS WRITE RIGHTS ANYWHERE!!!'); -} catch (err) { - log.print('VERY GOOD! USERS CANNOT WRITE ON YOUR DISK!'); - -} -throw new Error('Testing your error handling'); diff --git a/mod_actions/webapi/webapi.js b/mod_actions/webapi/webapi.js deleted file mode 100644 index 06a584a..0000000 --- a/mod_actions/webapi/webapi.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -/** - * Call any arbitrary webAPI. - * @param {Object} args the required function arguments object - * @param {String} args.url the required webAPI url - * @param {Object} [args.data] the data to be posted - * @param {Object} [args.credentials] optional credentials - * @param {String} [args.credentials.username] optional username - * @param {String} [args.credentials.password] optional password - */ -function call(args) { - if(!args || !args.url) { - console.error('ERROR in WebAPI AM call: Too few arguments!'); - return null; - } - needle.post(args.url, - args.data, - args.credentials, - function(error, response, body) { - if (!error) console.log('Successful webAPI AM call to ' + args.url); - else console.error('Error during webAPI AM call to ' + args.url - + ': ' + error.message); - } - ); -}; - -exports.call = call; - diff --git a/mod_events/probinder/probinder.js b/mod_events/probinder/probinder.js deleted file mode 100644 index 894aeea..0000000 --- a/mod_events/probinder/probinder.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -// var needle = require('needle'); - -/* - * ProBinder EVENT MODULE - */ - -var request = require('needle'), - urlService = 'https://probinder.com/service/', - credentials = null; - -function loadCredentials(cred) { - if(!cred || !cred.username || !cred.password) { - console.error('ERROR: ProBinder EM credentials file corrupt'); - } else { - credentials = cred; - console.log('Successfully loaded credentials for ProBinder EM'); - } -} - -/** - * Call the ProBinder service with the given parameters. - * @param {Object} args the required function arguments object - * @param {Object} [args.data] the data to be posted - * @param {String} args.service the required service identifier to be appended to the url - * @param {String} args.method the required method identifier to be appended to the url - * @param {function} [args.succes] the function to be called on success, - * receives the response body String or Buffer. - * @param {function} [args.error] the function to be called on error, - * receives an error, an http.ClientResponse object and a response body - * String or Buffer. - */ -function call(args) { - if(!args || !args.service || !args.method) { - console.error('ERROR in ProBinder EM call: Too few arguments!'); - return null; - } - if(credentials){ - needle.post(urlService + args.service + '/' + args.method, - args.data, - credentials, - function(error, response, body) { // The callback - if (!error) { //) && response.statusCode == 200) { - if(args && args.success) args.success(body); - } else { - if(args && args.error) args.error(error, response, body); - else console.error('ERROR during ProBinder EM call: ' + error.message); - } - } - ); - } else console.error('ProBinder EM request or credentials object not ready!'); -}; - -/** - * Calls the user's unread content service. - * @param {Object} [args] the optional object containing the success - * and error callback methods - */ -function unread(callback) { //FIXME ugly prop in here - - call({ - service: '36', - method: 'unreadcontent', - success: function(data) { - for(var i = 0; i < data.length; i++) callback(null, data[i]); - } - }); - -}; - -exports.loadCredentials = loadCredentials; -exports.call = call; -exports.unread = unread; - diff --git a/mod_events/testing/testing.js b/mod_events/testing/testing.js deleted file mode 100644 index 1a70ad0..0000000 --- a/mod_events/testing/testing.js +++ /dev/null @@ -1,23 +0,0 @@ - -/* -// Hacking my own system... - console.log(module.parent.parent.children[0].exports.getEventModuleAuth('probinder', - function(err, obj) {console.log(obj);})); -*/ - -//FIXME do not try to delete a file and rely on it to exist, rather try to create it first! o check for its existance and then delete it -try { - fs.unlinkSync(path.resolve(__dirname, 'event_modules', 'malicious', 'test.json')); - console.error('VERY BAD! NEVER START THIS SERVER WITH A USER THAT HAS WRITE RIGHTS ANYWHERE!!!'); -} catch (err) { - console.log('VERY GOOD! USERS CANNOT WRITE ON YOUR DISK!'); - -} - -//FIXME add several standard methods for testing (also rules to be inserted during testing) -throw new Error('Testing your error handling'); - -// FIXME catch these cases by instantiating a child process to run on a event retrieval -// then if the child_process doesn't end automatically after a certain time (statistics?) -// it ha sto be killed -// while (true) {} diff --git a/mod_events/weather/weather.js b/mod_events/weather/weather.js deleted file mode 100644 index e6f9881..0000000 --- a/mod_events/weather/weather.js +++ /dev/null @@ -1,29 +0,0 @@ - -var urlService = 'http://api.openweathermap.org/data/2.5/weather', - credentials, - old_temp; - -function loadCredentials(cred) { - if(!cred || !cred.key) { - console.error('ERROR in Weather EM: Weather event module credentials file corrupt'); - } else { - credentials = cred; - console.log('Successfully loaded credentials for Weather EM'); - } -} - -function tempRaisesAbove(prop, degree) { - needle.get(urlService + '?APPID=' + credentials.key + '&q=Basel', - function(error, response, body) { // The callback - if (!error) { //) && response.statusCode == 200) { - if(args && args.success) args.success(body); - } else { - if(args && args.error) args.error(error, response, body); - else console.error('Error during Weather EM tempRaisesAbove: ' + error.message); - } - } - ); -} - -exports.tempRaisesAbove = tempRaisesAbove; -exports.loadCredentials = loadCredentials; diff --git a/testing/test_engine.coffee b/testing/test_engine.coffee index c845121..e51aa3d 100644 --- a/testing/test_engine.coffee +++ b/testing/test_engine.coffee @@ -30,7 +30,7 @@ oRuleRealTwo = objects.rules.ruleRealTwo oAiOne = objects.ais.aiOne oAiTwo = objects.ais.aiTwo -exports.tearDown = ( cb ) -> +exports.setUp = ( cb ) -> engine.startEngine() cb() @@ -52,7 +52,7 @@ exports.tearDown = ( cb ) -> rule: oRuleRealTwo engine.shutDown() - setTimeout cb, 100 + setTimeout cb, 200 exports.ruleEvents = testInitAddDeleteMultiple: ( test ) -> @@ -145,7 +145,6 @@ exports.ruleEvents = exports.engine = testMatchingEvent: ( test ) -> test.expect 1 - db.storeUser oUser db.storeRule oRuleReal.id, JSON.stringify oRuleReal db.linkRule oRuleReal.id, oUser.username @@ -165,6 +164,7 @@ exports.engine = fWaitAgain = () -> db.getLog oUser.username, oRuleReal.id, ( err, data ) -> try + logged = data.split( '] ' )[1] logged = logged.split( "\n" )[0] test.strictEqual logged, "{#{ oAiOne.id }} " + evt.payload.property, 'Did not log the right thing' diff --git a/testing/test_persistence.coffee b/testing/test_persistence.coffee index dc746ef..7c8f578 100644 --- a/testing/test_persistence.coffee +++ b/testing/test_persistence.coffee @@ -494,7 +494,7 @@ exports.Rules = fWaitForDeletion = () -> db.deleteRule oRuleOne.id - setTimeout fWaitForTest, 300 + setTimeout fWaitForTest, 500 setTimeout fWaitForDeletion, 100 @@ -561,7 +561,6 @@ exports.User = db.getUserIds ( err, obj ) -> test.ok oUser.username in obj, 'User key was not stored!?' - db.deleteUser oUser.username test.done() testDelete: ( test ) -> diff --git a/testing/test_request-handler.coffee b/testing/test_request-handler.coffee index 3d6e39a..208e913 100644 --- a/testing/test_request-handler.coffee +++ b/testing/test_request-handler.coffee @@ -3,7 +3,6 @@ fs = require 'fs' path = require 'path' events = require 'events' cp = require 'child_process' -qs = require 'querystring' try @@ -98,10 +97,10 @@ exports.session = test.done() rh.handleLogout req, resp # set the handler to listening rh.handleLogin req, resp # set the handler to listening - postRequestData req, qs.stringify @oUsr # emit the data post event + postRequestData req, JSON.stringify @oUsr # emit the data post event rh.handleLogin req, resp # set the handler to listening - postRequestData req, qs.stringify @oUsr # emit the data post event + postRequestData req, JSON.stringify @oUsr # emit the data post event testWrongLogin: ( test ) => @@ -117,7 +116,7 @@ exports.session = username: @oUsr.username password: 'wrongpassword' rh.handleLogin req, resp # set the handler to listening - postRequestData req, qs.stringify usr # emit the data post event + postRequestData req, JSON.stringify usr # emit the data post event exports.events = setUp: ( cb ) -> @@ -170,7 +169,7 @@ exports.events = test.done() rh.handleEvent req, resp # set the handler to listening - postRequestData req, qs.stringify oEvt # emit the data post event + postRequestData req, JSON.stringify oEvt # emit the data post event setTimeout fPopEvent, 200 # try to fetch the db entry exports.testLoginOrPage = ( test ) -> @@ -243,5 +242,5 @@ exports.testUserCommands = ( test ) -> test.deepEqual msg, oRespData, 'Service didn\'t return expected' test.done() rh.handleUserCommand req, resp # set the handler to listening - postRequestData req, qs.stringify oReqData # emit the data post event + postRequestData req, JSON.stringify oReqData # emit the data post event diff --git a/webpages/handlers/coffee/edit_modules.coffee b/webpages/handlers/coffee/edit_modules.coffee index 5e503d6..2cc3aac 100644 --- a/webpages/handlers/coffee/edit_modules.coffee +++ b/webpages/handlers/coffee/edit_modules.coffee @@ -16,19 +16,22 @@ fOnLoad = () -> fErrHandler = ( errMsg ) -> ( err ) -> - $( '#moduleName' ).html "