Updated tests in DB interface

This commit is contained in:
Dominic Bosch 2014-02-10 22:28:10 +01:00
parent 5a13beadd0
commit 8fbe21094b
22 changed files with 2083 additions and 482 deletions

View file

@ -3,18 +3,18 @@
DB Interface DB Interface
============ ============
> Handles the connection to the database and provides functionalities for > Handles the connection to the database and provides functionalities for
> event/action modules, rules and the encrypted storing of authentication tokens. > event pollers, action invokers, rules and the encrypted storing of authentication tokens.
> General functionality as a wrapper for the module holds initialization, > General functionality as a wrapper for the module holds initialization,
> encryption/decryption, the retrieval of modules and shut down. > encryption/decryption, the retrieval of modules and shut down.
> >
> The general structure for linked data is that the key is stored in a set. > The general structure for linked data is that the key is stored in a set.
> By fetching all set entries we can then fetch all elements, which is > By fetching all set entries we can then fetch all elements, which is
> automated in this function. > automated in this function.
> For example modules of the same group, e.g. action modules are registered in an > For example, modules of the same group, e.g. action invokers are registered in an
> unordered set in the database, from where they can be retrieved again. For example > unordered set in the database, from where they can be retrieved again. For example
> a new action module has its ID (e.g 'probinder') first registered in the set > a new action invoker has its ID (e.g 'probinder') first registered in the set
> 'action_modules' and then stored in the db with the key 'action\_module\_' + ID > 'action-invokers' and then stored in the db with the key 'action-invoker:' + ID
> (e.g. action\_module\_probinder). > (e.g. action-invoker:probinder).
> >
### ###
@ -50,6 +50,8 @@ exports = module.exports = ( args ) =>
@db.on 'error', ( err ) -> @db.on 'error', ( err ) ->
err.addInfo = 'message from DB' err.addInfo = 'message from DB'
log.error 'DB', err log.error 'DB', err
@ep = new IndexedModules( 'event-poller', @db )
@ai = new IndexedModules( 'action-invoker', @db )
else else
log.error 'DB', 'Initialization failed because of missing config file!' log.error 'DB', 'Initialization failed because of missing config file!'
@ -83,7 +85,7 @@ Abstracts logging for simple action replies from the DB.
replyHandler = ( action ) -> replyHandler = ( action ) ->
( err, reply ) -> ( err, reply ) ->
if err if err
err.addInfo = "during \"#{ action }\"" err.addInfo = "during '#{ action }'"
log.error 'DB', err log.error 'DB', err
else else
log.print 'DB', "#{ action }: #{ reply }" log.print 'DB', "#{ action }: #{ reply }"
@ -96,14 +98,14 @@ Push an event into the event queue.
### ###
exports.pushEvent = ( oEvent ) => exports.pushEvent = ( oEvent ) =>
if oEvent if oEvent
log.print 'DB', "Event pushed into the queue: #{ oEvent.eventid }" log.print 'DB', "Event pushed into the queue: '#{ oEvent.eventid }'"
@db.rpush 'event_queue', JSON.stringify( oEvent ) @db.rpush 'event_queue', JSON.stringify( oEvent )
else else
log.error 'DB', 'Why would you give me an empty event...' log.error 'DB', 'Why would you give me an empty event...'
### ###
Pop an event from the event queue and pass it to the callback(err, obj) function. Pop an event from the event queue and pass it to cb(err, obj).
@public popEvent( *cb* ) @public popEvent( *cb* )
@param {function} cb @param {function} cb
@ -146,10 +148,8 @@ Encrypts a string using the crypto key from the config file, based on aes-256-cb
### ###
encrypt = ( plainText ) => encrypt = ( plainText ) =>
if !plainText? then return null if !plainText? then return null
try try
enciph = crypto.createCipher 'aes-256-cbc', @crypto_key crypto.AES.encrypt plainText, @crypto_key
et = enciph.update plainText, 'utf8', 'base64'
et + enciph.final 'base64'
catch err catch err
err.addInfo = 'during encryption' err.addInfo = 'during encryption'
log.error 'DB', err log.error 'DB', err
@ -164,203 +164,309 @@ Decrypts an encrypted string and hands it back on success or null.
decrypt = ( crypticText ) => decrypt = ( crypticText ) =>
if !crypticText? then return null; if !crypticText? then return null;
try try
deciph = crypto.createDecipher 'aes-256-cbc', @crypto_key dec = crypto.AES.decrypt crypticText, @crypto_key
dt = deciph.update crypticText, 'base64', 'utf8' dec.toString(crypto.enc.Utf8)
dt + deciph.final 'utf8'
catch err catch err
err.addInfo = 'during decryption' err.addInfo = 'during decryption'
log.error 'DB', err log.error 'DB', err
null null
### ###
Fetches all linked data set keys from a linking set, fetches the single data objects Fetches all linked data set keys from a linking set, fetches the single
via the provided function and returns the results to the callback(err, obj) function. data objects via the provided function and returns the results to cb(err, obj).
@private getSetRecords( *set, fSingle, cb* ) @private getSetRecords( *set, fSingle, cb* )
@param {String} set the set name how it is stored in the DB @param {String} set the set name how it is stored in the DB
@param {function} fSingle a function to retrieve a single data element per set entry @param {function} fSingle a function to retrieve a single data element
@param {function} cb the callback(err, obj) function that receives all the retrieved data or an error per set entry
@param {function} cb the callback(err, obj) function that receives all
the retrieved data or an error
### ###
getSetRecords = ( set, fSingle, cb ) => getSetRecords = ( set, fSingle, cb ) =>
log.print 'DB', "Fetching set records: #{ set }" log.print 'DB', "Fetching set records: '#{ set }'"
# Fetch all members of the set
@db.smembers set, ( err, arrReply ) -> @db.smembers set, ( err, arrReply ) ->
if err if err
err.addInfo = "fetching #{ set }" # If an error happens we return it to the callback function
err.addInfo = "fetching '#{ set }'"
log.error 'DB', err log.error 'DB', err
cb err
else if arrReply.length == 0 else if arrReply.length == 0
# If the set was empty we return null to the callback
cb() cb()
else else
# We need to fetch all the entries from the set and use a semaphore
# since the fetching from the DB will happen asynchronously
semaphore = arrReply.length semaphore = arrReply.length
objReplies = {} objReplies = {}
setTimeout -> setTimeout ->
# We use a timeout function to cancel the operation
# in case the DB does not respond
if semaphore > 0 if semaphore > 0
cb new Error "Timeout fetching #{ set }" cb new Error "Timeout fetching '#{ set }'"
, 2000 , 2000
fCallback = ( prop ) -> fCallback = ( prop ) ->
# The callback function is required to preprocess the result before
# handing it to the callback. This especially includes decrementing
# the semaphore
( err, data ) -> ( err, data ) ->
--semaphore --semaphore
if err if err
err.addInfo = "fetching single element: #{ prop }" err.addInfo = "fetching single element: '#{ prop }'"
log.error 'DB', err log.error 'DB', err
else if not data else if not data
log.error 'DB', new Error "Empty key in DB: #{ prop }" # There was no data behind the key
log.error 'DB', new Error "Empty key in DB: '#{ prop }'"
else else
# We found a valid record and add it to the reply object
objReplies[ prop ] = data objReplies[ prop ] = data
if semaphore == 0 if semaphore == 0
# If all fetch calls returned we finally pass the result
# to the callback
cb null, objReplies cb null, objReplies
# Since we retrieved an array of keys, we now execute the fSingle function
# on each of them, to retrieve the ata behind the key. Our fCallback function
# is used to preprocess the answer to determine correct execution
fSingle reply, fCallback( reply ) for reply in arrReply fSingle reply, fCallback( reply ) for reply in arrReply
class IndexedModules
constructor: ( @setname, @db ) ->
log.print 'DB', "Instantiated indexed modules for '#{ @setname }'"
storeModule: ( mId, data ) =>
log.print 'DB', "storeModule(#{ @setname }): #{ mId }"
@db.sadd "#{ @setname }s", mId,
replyHandler "Storing '#{ @setname }' key '#{ mId }'"
@db.set "#{ @setname }:#{ mId }", data,
replyHandler "Storing '#{ @setname }:#{ mId }'"
getModule: ( mId, cb ) =>
log.print 'DB', "getModule('#{ @setname }): #{ mId }'"
@db.get "#{ @setname }:#{ mId }", cb
getModuleIds: ( cb ) =>
log.print 'DB', "getModuleIds(#{ @setname })"
@db.smembers "#{ @setname }s", cb
getModules: ( cb ) =>
log.print 'DB', "getModules(#{ @setname })"
getSetRecords "#{ @setname }s", @getModule, cb
deleteModule: ( mId ) =>
log.print 'DB', "deleteModule(#{ @setname }): #{ mId }"
@db.srem "#{ @setname }s", mId,
replyHandler "Deleting '#{ @setname }' key '#{ mId }'"
@db.del "#{ @setname }:#{ mId }",
replyHandler "Deleting '#{ @setname }:#{ mId }'"
storeParameters: ( mId, userId, data ) =>
log.print 'DB', "storeParameters(#{ @setname }): '#{ mId }:#{ userId }'"
@db.sadd "#{ @setname }-params", "#{ mId }:#{ userId }",
replyHandler "Storing '#{ @setname }' module parameters key '#{ mId }'"
@db.set "#{ @setname }-params:#{ mId }:#{ userId }", encrypt(data),
replyHandler "Storing '#{ @setname }' module parameters '#{ mId }:#{ userId }'"
getParameters: ( mId, userId, cb ) =>
log.print 'DB', "getParameters(#{ @setname }): '#{ mId }:#{ userId }'"
@db.get "#{ @setname }-params:#{ mId }:#{ userId }", ( err, data ) ->
cb err, decrypt data
getParametersIds: ( cb ) =>
log.print 'DB', "getParametersIds(#{ @setname })"
@db.smembers "#{ @setname }-params", cb
deleteParameters: ( mId, userId ) =>
log.print 'DB', "deleteParameters(#{ @setname }): '#{ mId }:#{ userId }'"
@db.srem "#{ @setname }-params", "#{ mId }:#{ userId }",
replyHandler "Deleting '#{ @setname }-params' key '#{ mId }:#{ userId }'"
@db.del "#{ @setname }-params:#{ mId }:#{ userId }",
replyHandler "Deleting '#{ @setname }-params:#{ mId }:#{ userId }'"
### ###
## Action Modules ## Action Invokers
#TODO Rename Action Modules into something like Action Caller
### ###
### ###
Store a string representation of an action module in the DB. Store a string representation of an action invoker in the DB.
@public storeActionModule ( *amId, data* ) @public storeActionInvoker ( *aiId, data* )
@param {String} amId @param {String} aiId
@param {String} data @param {String} data
### ###
exports.storeActionModule = ( amId, data ) => exports.storeActionInvoker = ( aiId, data ) =>
log.print 'DB', "storeActionModule: #{ amId }" @ai.storeModule( aiId, data )
@db.sadd 'action-modules', amId, replyHandler "storing action module key #{ amId }"
@db.set "action-module:#{ amId }", data, replyHandler "storing action module #{ amId }"
### ###
Query the DB for an action module and pass it to the callback(err, obj) function. Query the DB for an action invoker and pass it to cb(err, obj).
@public getActionModule( *amId, cb* ) @public getActionInvoker( *aiId, cb* )
@param {String} amId @param {String} aiId
@param {function} cb @param {function} cb
### ###
exports.getActionModule = ( amId, cb ) => exports.getActionInvoker = ( aiId, cb ) =>
log.print 'DB', "getActionModule: #{ amId }" @ai.getModule aiId, cb
@db.get "action-module:#{ amId }", cb
exports.getSetMembers = ( setId, cb ) =>
@db.smembers setId, cb
### ###
Fetch all action module IDs and hand them to the callback(err, obj) function. Fetch all action invoker IDs and hand them to cb(err, obj).
@public getActionModuleIds( *cb* ) @public getActionInvokerIds( *cb* )
@param {function} cb @param {function} cb
### ###
exports.getActionModuleIds = ( cb ) => exports.getActionInvokerIds = ( cb ) =>
@db.smembers 'action-modules', cb @ai.getModuleIds cb
### ###
Fetch all action modules and hand them to the callback(err, obj) function. Fetch all action invokers and hand them to cb(err, obj).
@public getActionModules( *cb* ) @public getActionInvokers( *cb* )
@param {function} cb @param {function} cb
### ###
exports.getActionModules = ( cb ) -> exports.getActionInvokers = ( cb ) =>
getSetRecords 'action-modules', exports.getActionModule, cb @ai.getModules cb
### ###
Fetch all action modules and hand them to the callback(err, obj) function. Fetch all action invokers and hand them to cb(err, obj).
@public getActionModules( *cb* ) @public getActionInvokers( *cb* )
@param {function} cb @param {function} cb
### ###
exports.deleteActionModule = ( amId ) => exports.deleteActionInvoker = ( aiId ) =>
@db.srem 'action-modules', amId, replyHandler "deleting action module key #{ amId }" @ai.deleteModule aiId
@db.del "action-module:#{ amId }", replyHandler "deleting action module #{ amId }"
### ###
Store user-specific action module parameters . Store user-specific action invoker parameters .
@public storeActionParams( *userId, amId, data* ) @public storeActionParams( *userId, aiId, data* )
@param {String} userId @param {String} userId
@param {String} amId @param {String} aiId
@param {String} data @param {String} data
### ###
exports.storeActionParams = ( userId, amId, data ) => exports.storeActionParams = ( aiId, userId, data ) =>
log.print 'DB', "storeActionParams: #{ amId }:#{ userId }" @ai.storeParameters aiId, userId, data
@db.set "action-params:#{ amId }:#{ userId }", hash(data),
replyHandler "storing action params #{ amId }:#{ userId }"
### ###
Query the DB for user-specific action module parameters, Query the DB for user-specific action module parameters,
and pass it to the callback(err, obj) function. and pass it to cb(err, obj).
@public getActionParams( *userId, amId, cb* ) @public getActionParams( *userId, aiId, cb* )
@param {String} userId @param {String} userId
@param {String} amId @param {String} aiId
@param {function} cb @param {function} cb
### ###
exports.getActionParams = ( userId, amId, cb ) => exports.getActionParams = ( aiId, userId, cb ) =>
log.print 'DB', "getActionParams: #{ amId }:#{ userId }" @ai.getParameters aiId, userId, cb
@db.get "action-params:#{ amId }:#{ userId }", ( err, data ) ->
cb err, decrypt data ###
Fetch all action params IDs and hand them to cb(err, obj).
@public getActionParamsIds( *cb* )
@param {function} cb
###
exports.getActionParamsIds = ( cb ) =>
@ai.getParametersIds cb
###
Fetch all action modules and hand them to cb(err, obj).
@public deleteActionParams( *cb* )
@param {function} cb
###
exports.deleteActionParams = ( aiId, userId ) =>
@ai.deleteParameters aiId, userId
### ###
## Event Modules ## Event Pollers
#TODO rename event modules to event puller or something like that
### ###
### ###
Store a string representation of an event module in the DB. Store a string representation of an event poller in the DB.
@public storeEventModule( *emId, data* ) @public storeEventPoller ( *epId, data* )
@param {String} emId @param {String} epId
@param {String} data @param {String} data
### ###
exports.storeEventModule = ( emId, data ) => exports.storeEventPoller = ( epId, data ) =>
log.print 'DB', "storeEventModule: #{ emId }" @ep.storeModule( epId, data )
@db.sadd 'event-modules', emId, replyHandler "storing event module key #{ emId }"
@db.set 'event-module:#{ emId }', data, replyHandler "storing event module #{ emId }"
### ###
Query the DB for an event module and pass it to the callback(err, obj) function. Query the DB for an event poller and pass it to cb(err, obj).
@public getEventModule( *emId, cb* ) @public getEventPoller( *epId, cb* )
@param {String} emId @param {String} epId
@param {function} cb @param {function} cb
### ###
exports.getEventModule = ( emId, cb ) => exports.getEventPoller = ( epId, cb ) =>
log.print 'DB', "getEventModule: #{ emId }" @ep.getModule epId, cb
@db.get "event-module:#{ emId }", cb
### ###
Fetch all event modules and pass them to the callback(err, obj) function. Fetch all event poller IDs and hand them to cb(err, obj).
@public getEventModules( *cb* ) @public getEventPollerIds( *cb* )
@param {function} cb @param {function} cb
### ###
exports.getEventModules = ( cb ) -> exports.getEventPollerIds = ( cb ) =>
getSetRecords 'event-modules', exports.getEventModule, cb @ep.getModuleIds cb
### ###
Store a string representation of user-specific parameters for an event module. Fetch all event pollers and hand them to cb(err, obj).
@public storeEventParams( *userId, emId, data* ) @public getEventPollers( *cb* )
@param {function} cb
###
exports.getEventPollers = ( cb ) =>
@ep.getModules cb
###
Fetch all event pollers and hand them to cb(err, obj).
@public getEventPollers( *cb* )
@param {function} cb
###
exports.deleteEventPoller = ( epId ) =>
@ep.deleteModule epId
###
Store user-specific event poller parameters .
@public storeEventParams( *userId, epId, data* )
@param {String} userId @param {String} userId
@param {String} emId @param {String} epId
@param {Object} data @param {String} data
### ###
# TODO is used, remove unused ones exports.storeEventParams = ( epId, userId, data ) =>
exports.storeEventParams = ( userId, emId, data ) => @ep.storeParameters epId, userId, data
log.print 'DB', "storeEventParams: #{ emId }:#{ userId }"
# TODO encryption based on user specific key?
@db.set "event-params:#{ emId }:#{ userId }", encrypt(data),
replyHandler "storing event auth #{ emId }:#{ userId }"
###
Query the DB for an action module authentication token, associated with a user.
@public getEventAuth( *userId, emId, data* ) ###
Query the DB for user-specific event module parameters,
and pass it to cb(err, obj).
@public getEventParams( *userId, epId, cb* )
@param {String} userId @param {String} userId
@param {String} emId @param {String} epId
@param {function} cb @param {function} cb
### ###
exports.getEventAuth = ( userId, emId, cb ) => exports.getEventParams = ( epId, userId, cb ) =>
log.print 'DB', "getEventAuth: #{ emId }:#{ userId }" @ep.getParameters epId, userId, cb
@db.get "event-auth:#{ emId }:#{ userId }", ( err, data ) ->
cb err, decrypt data ###
Fetch all event params IDs and hand them to cb(err, obj).
@public getEventParamsIds( *cb* )
@param {function} cb
###
exports.getEventParamsIds = ( cb ) =>
@ep.getParametersIds cb
###
Fetch all event modules and hand them to cb(err, obj).
@public deleteEventParams( *cb* )
@param {function} cb
###
exports.deleteEventParams = ( epId, userId ) =>
@ep.deleteParameters epId, userId
### ###
@ -368,33 +474,18 @@ exports.getEventAuth = ( userId, emId, cb ) =>
### ###
### ###
Store a string representation of a rule in the DB. Query the DB for a rule and pass it to cb(err, obj).
@public storeRule( *ruleId, userId, data* )
@param {String} ruleId
@param {String} userId
@param {String} data
###
exports.storeRule = ( ruleId, userId, data ) =>
log.print 'DB', "storeRule: #{ ruleId }"
@db.sadd 'rules', "#{ ruleId }:#{ userId }", replyHandler "storing rule key \"#{ ruleId }:#{ userId }\""
@db.sadd "user-set:#{ userId }:rules", ruleId, replyHandler "storing rule key to \"user:#{ userId }:rules\""
@db.sadd "rule-set:#{ ruleId }:users", user, replyHandler "storing user key to \"rule:#{ ruleId }:users\""
@db.set "rule:#{ ruleId }:#{ userId }", data, replyHandler "storing rule \"#{ ruleId }:#{ userId }\""
###
Query the DB for a rule and pass it to the callback(err, obj) function.
@public getRule( *ruleId, cb* ) @public getRule( *ruleId, cb* )
@param {String} ruleId @param {String} ruleId
@param {function} cb @param {function} cb
### ###
exports.getRule = ( ruleId, cb ) => exports.getRule = ( ruleId, cb ) =>
log.print 'DB', "getRule: #{ ruleId }" log.print 'DB', "getRule: '#{ ruleId }'"
@db.get "rule:#{ ruleId }", cb @db.get "rule:#{ ruleId }", cb
### ###
Fetch all rules from the database and pass them to the callback function. Fetch all rules and pass them to cb(err, obj).
@public getRules( *cb* ) @public getRules( *cb* )
@param {function} cb @param {function} cb
@ -403,6 +494,203 @@ exports.getRules = ( cb ) ->
log.print 'DB', 'Fetching all Rules' log.print 'DB', 'Fetching all Rules'
getSetRecords 'rules', exports.getRule, cb getSetRecords 'rules', exports.getRule, cb
###
Fetch all rule IDs and hand it to cb(err, obj).
@public getRuleIds( *cb* )
@param {function} cb
###
exports.getRuleIds = ( cb ) =>
log.print 'DB', 'Fetching all Rule IDs'
@db.smembers 'rules', cb
###
Store a string representation of a rule in the DB.
@public storeRule( *ruleId, data* )
@param {String} ruleId
@param {String} data
###
exports.storeRule = ( ruleId, data ) =>
log.print 'DB', "storeRule: '#{ ruleId }'"
@db.sadd 'rules', "#{ ruleId }",
replyHandler "storing rule key '#{ ruleId }'"
@db.set "rule:#{ ruleId }", data,
replyHandler "storing rule '#{ ruleId }'"
###
Delete a string representation of a rule.
@public deleteRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
###
exports.deleteRule = ( ruleId ) =>
log.print 'DB', "deleteRule: '#{ ruleId }'"
@db.srem "rules", ruleId, replyHandler "Deleting rule key '#{ ruleId }'"
@db.del "rule:#{ ruleId }", replyHandler "Deleting rule '#{ ruleId }'"
# We also need to delete all references in linked and active users
@db.smembers "rule:#{ ruleId }:users", ( err, obj ) =>
delLinkedUserRule = ( userId ) =>
@db.srem "user:#{ userId }:rules", ruleId,
replyHandler "Deleting rule key '#{ ruleId }'' in linked user '#{ userId }'"
delLinkedUserRule( id ) for id in obj
@db.del "rule:#{ ruleId }:users", replyHandler "Deleting 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 }'"
delActiveUserRule( id ) for id in obj
@db.del "rule:#{ ruleId }:active-users",
replyHandler "Deleting rule '#{ ruleId }' active users"
###
Associate a rule to a user.
@public linkRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
###
exports.linkRule = ( ruleId, userId ) =>
log.print 'DB', "linkRule: '#{ ruleId }' for user '#{ userId }'"
@db.sadd "rule:#{ ruleId }:users", userId,
replyHandler "storing user '#{ userId }' for rule key '#{ ruleId }'"
@db.sadd "user:#{ userId }:rules", ruleId,
replyHandler "storing rule key '#{ ruleId }' for user '#{ userId }'"
###
Get rules linked to a user and hand it to cb(err, obj).
@public getUserLinkRule( *userId, cb* )
@param {String} userId
@param {function} cb
###
exports.getUserLinkedRules = ( userId, cb ) =>
log.print 'DB', "getUserLinkedRules: for user '#{ userId }'"
@db.smembers "user:#{ userId }:rules", cb
###
Get users linked to a rule and hand it to cb(err, obj).
@public getRuleLinkedUsers( *ruleId, cb* )
@param {String} ruleId
@param {function} cb
###
exports.getRuleLinkedUsers = ( ruleId, cb ) =>
log.print 'DB', "getRuleLinkedUsers: for rule '#{ ruleId }'"
@db.smembers "rule:#{ ruleId }:users", cb
###
Delete an association of a rule to a user.
@public unlinkRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
###
exports.unlinkRule = ( ruleId, userId ) =>
log.print 'DB', "unlinkRule: '#{ ruleId }:#{ userId }'"
@db.srem "rule:#{ ruleId }:users", userId,
replyHandler "removing user '#{ userId }' for rule key '#{ ruleId }'"
@db.srem "user:#{ userId }:rules", ruleId,
replyHandler "removing rule key '#{ ruleId }' for user '#{ userId }'"
###
Activate a rule.
@public activateRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
###
exports.activateRule = ( ruleId, userId ) =>
log.print 'DB', "activateRule: '#{ ruleId }' for '#{ userId }'"
@db.sadd "rule:#{ ruleId }:active-users", userId,
replyHandler "storing activated user '#{ userId }' in rule '#{ ruleId }'"
@db.sadd "user:#{ userId }:active-rules", ruleId,
replyHandler "storing activated rule '#{ ruleId }' in user '#{ userId }'"
###
Get rules activated for a user and hand it to cb(err, obj).
@public getUserLinkRule( *userId, cb* )
@param {String} userId
@param {function} cb
###
exports.getUserActivatedRules = ( userId, cb ) =>
log.print 'DB', "getUserActivatedRules: for user '#{ userId }'"
@db.smembers "user:#{ userId }:active-rules", cb
###
Get users activated for a rule and hand it to cb(err, obj).
@public getRuleActivatedUsers ( *ruleId, cb* )
@param {String} ruleId
@param {function} cb
###
exports.getRuleActivatedUsers = ( ruleId, cb ) =>
log.print 'DB', "getRuleLinkedUsers: for rule '#{ ruleId }'"
@db.smembers "rule:#{ ruleId }:active-users", cb
###
Deactivate a rule.
@public deactivateRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
###
exports.deactivateRule = ( ruleId, userId ) =>
log.print 'DB', "deactivateRule: '#{ ruleId }' for '#{ userId }'"
@db.srem "rule:#{ ruleId }:active-users", userId,
replyHandler "removing activated user '#{ userId }' in rule '#{ ruleId }'"
@db.srem "user:#{ userId }:active-rules", ruleId,
replyHandler "removing activated rule '#{ ruleId }' in user '#{ userId }'"
###
Fetch all active ruleIds and pass them to cb(err, obj).
@public getAllActivatedRuleIds( *cb* )
@param {function} cb
###
exports.getAllActivatedRuleIdsPerUser = ( cb ) =>
log.print 'DB', "Fetching all active rules"
@db.smembers 'users', ( err, obj ) =>
result = {}
console.log 'checking length'
if obj.length is 0
console.log 'length cehcked is 0'
cb null, result
else
console.log 'length cehcked'
semaphore = obj.length
fFetchActiveUserRules = ( userId ) =>
@db.smembers "user:#{ user }:active-rules", ( err, obj ) =>
console.log obj
console.log obj.length
if obj.length is 0
console.log 'is 0'
else
result[userId] = obj
if --semaphore is 0
cb null, result
fFetchActiveUserRules(user) for user in obj
###
Fetch all active rules and pass them to cb(err, obj).
@public getAllActivatedRules( *cb* )
@param {function} cb
###
exports.getAllActivatedRules = ( cb ) =>
log.print 'DB', "Fetching all active rules"
fCb = ( err, obj ) ->
console.log 'fetched something'
console.log err
console.log obj
@db.smembers 'users', ( err, obj ) =>
getSetRecords "user:#{ user }:active-rules", exports.getRule, fCb for user in obj
### ###
Store a user object (needs to be a flat structure). Store a user object (needs to be a flat structure).
@ -412,11 +700,13 @@ Store a user object (needs to be a flat structure).
exports.storeUser = ( objUser ) => exports.storeUser = ( objUser ) =>
#TODO Only store user if not already existing, or at least only then add a private key #TODO Only store user if not already existing, or at least only then add a private key
#for his encryption. we would want to have one private key per user, right? #for his encryption. we would want to have one private key per user, right?
log.print 'DB', "storeUser: #{ objUser.username }" log.print 'DB', "storeUser: '#{ objUser.username }'"
if objUser and objUser.username and objUser.password if objUser and objUser.username and objUser.password
@db.sadd 'users', objUser.username, replyHandler "storing user key #{ objUser.username }" @db.sadd 'users', objUser.username,
replyHandler "storing user key '#{ objUser.username }'"
objUser.password = hash objUser.password objUser.password = hash objUser.password
@db.hmset "user:#{ objUser.username }", objUser, replyHandler "storing user properties #{ objUser.username }" @db.hmset "user:#{ objUser.username }", objUser,
replyHandler "storing user properties '#{ objUser.username }'"
else else
log.error 'DB', new Error 'username or password was missing' log.error 'DB', new Error 'username or password was missing'
@ -428,29 +718,31 @@ Associate a role with a user.
@param {String} role @param {String} role
### ###
exports.storeUserRole = ( userId, role ) => exports.storeUserRole = ( userId, role ) =>
log.print 'DB', "storeUserRole: #{ userId }:#{ role }" log.print 'DB', "storeUserRole: '#{ userId }:#{ role }'"
@db.sadd 'roles', role, replyHandler "adding role #{ role } to role index set" @db.sadd 'roles', role, replyHandler "adding role '#{ role }' to role index set"
@db.sadd "user:#{ userId }:roles", role, replyHandler "adding role #{ role } to user #{ userId }" @db.sadd "user:#{ userId }:roles", role,
@db.sadd "role:#{ role }:users", userId, replyHandler "adding user #{ userId } to role #{ role }" replyHandler "adding role '#{ role }' to user '#{ userId }'"
@db.sadd "role:#{ role }:users", userId,
replyHandler "adding user '#{ userId }' to role '#{ role }'"
### ###
Fetch all roles of a user and pass them to the callback(err, obj) Fetch all roles of a user and pass them to cb(err, obj).
@public getUserRoles( *userId* ) @public getUserRoles( *userId* )
@param {String} userId @param {String} userId
### ###
exports.getUserRoles = ( userId ) => exports.getUserRoles = ( userId ) =>
log.print 'DB', "getUserRole: #{ userId }" log.print 'DB', "getUserRole: '#{ userId }'"
@db.get "user-roles:#{ userId }", cb @db.get "user-roles:#{ userId }", cb
### ###
Fetch all users of a role and pass them to the callback(err, obj) Fetch all users of a role and pass them to cb(err, obj).
@public getUserRoles( *role* ) @public getUserRoles( *role* )
@param {String} role @param {String} role
### ###
exports.getRoleUsers = ( role ) => exports.getRoleUsers = ( role ) =>
log.print 'DB', "getRoleUsers: #{ role }" log.print 'DB', "getRoleUsers: '#{ role }'"
@db.get "role-users:#{ role }", cb @db.get "role-users:#{ role }", cb
### ###
@ -466,14 +758,14 @@ because we only store hashes of passwords for safety reasons.
### ###
#TODO verify and test whole function #TODO verify and test whole function
exports.loginUser = ( userId, password, cb ) => exports.loginUser = ( userId, password, cb ) =>
log.print 'DB', "User \"#{ userId }\" tries to log in" log.print 'DB', "User '#{ userId }' tries to log in"
fCheck = ( pw ) -> fCheck = ( pw ) ->
( err, obj ) -> ( err, obj ) ->
if err if err
cb err cb err
else if obj and obj.password else if obj and obj.password
if pw == obj.password if pw == obj.password
log.print 'DB', "User \"#{ obj.username }\" logged in!" log.print 'DB', "User '#{ obj.username }' logged in!"
cb null, obj cb null, obj
else else
cb new Error 'Wrong credentials!' cb new Error 'Wrong credentials!'
@ -481,7 +773,36 @@ exports.loginUser = ( userId, password, cb ) =>
cb new Error 'User not found!' cb new Error 'User not found!'
@db.hgetall "user:#{ userId }", fCheck password @db.hgetall "user:#{ userId }", fCheck password
#TODO implement functions required for user sessions and the rule activation ###
Deletes a user and all his associated linked and active rules.
@public deleteUser( *userId* )
@param {String} userId
###
exports.deleteUser = ( userId ) =>
log.print 'DB', "deleteUser: '#{ userId }'"
@db.srem "users", userId, replyHandler "Deleting user key '#{ userId }'"
@db.del "user:#{ userId }", replyHandler "Deleting user '#{ userId }'"
# We also need to delete all linked rules
@db.smembers "user:#{ userId }:rules", ( err, obj ) =>
delLinkedRuleUser = ( ruleId ) =>
@db.srem "rule:#{ ruleId }:users", userId,
replyHandler "Deleting user key '#{ userId }' in linked rule '#{ ruleId }'"
delLinkedRuleUser( id ) for id in obj
@db.del "user:#{ userId }:rules",
replyHandler "Deleting user '#{ userId }' rules"
# We also need to delete all active rules
@db.smembers "user:#{ userId }:rules", ( err, obj ) =>
delActivatedRuleUser = ( ruleId ) =>
@db.srem "rule:#{ ruleId }:active-users", userId,
replyHandler "Deleting user key '#{ userId }' in active rule '#{ ruleId }'"
delActivatedRuleUser( id ) for id in obj
@db.del "user:#{ userId }:active-rules", replyHandler "Deleting user '#{ userId }' rules"
#TODO implement functions required for user sessions?
### ###
Shuts down the db link. Shuts down the db link.

View file

@ -160,6 +160,16 @@ Resolves the path to a handler webpage and returns it as a string.
getHandlerFileAsString = ( name ) -> getHandlerFileAsString = ( name ) ->
fs.readFileSync getHandlerPath( name ), 'utf8' fs.readFileSync getHandlerPath( name ), 'utf8'
###
Fetches an include file.
@private getIncludeFileAsString( *name* )
@param {String} name
###
getIncludeFileAsString = ( name ) ->
pth = path.resolve __dirname, '..', 'webpages', 'handlers', 'includes', name + '.html'
fs.readFileSync pth, 'utf8'
### ###
Renders a page depending on the user session and returns it. Renders a page depending on the user session and returns it.
@ -169,8 +179,8 @@ Renders a page depending on the user session and returns it.
### ###
renderPage = ( name, sess, msg ) -> renderPage = ( name, sess, msg ) ->
template = getHandlerFileAsString name template = getHandlerFileAsString name
menubar = getHandlerFileAsString 'part_menubar' menubar = getIncludeFileAsString 'menubar'
requires = getHandlerFileAsString 'part_requires' requires = getIncludeFileAsString 'requires'
view = view =
user: sess.user, user: sess.user,
head_requires: requires, head_requires: requires,
@ -190,10 +200,14 @@ objects.*
@param {String} pagename @param {String} pagename
### ###
sendLoginOrPage = ( pagename, req, resp ) -> sendLoginOrPage = ( pagename, req, resp ) ->
if req.session and req.session.user if !req.session
resp.send renderPage pagename, req.session req.session = {}
else if !req.session.user
resp.sendfile getHandlerPath 'login' pagename = 'login'
# resp.send renderPage pagename, req.session
# else
# resp.sendfile getHandlerPath 'login'
resp.send renderPage pagename, req.session
### ###
Present the module forge to the user. Present the module forge to the user.

View file

@ -4,25 +4,26 @@
DB Interface DB Interface
============ ============
> Handles the connection to the database and provides functionalities for > Handles the connection to the database and provides functionalities for
> event/action modules, rules and the encrypted storing of authentication tokens. > event pollers, action invokers, rules and the encrypted storing of authentication tokens.
> General functionality as a wrapper for the module holds initialization, > General functionality as a wrapper for the module holds initialization,
> encryption/decryption, the retrieval of modules and shut down. > encryption/decryption, the retrieval of modules and shut down.
> >
> The general structure for linked data is that the key is stored in a set. > The general structure for linked data is that the key is stored in a set.
> By fetching all set entries we can then fetch all elements, which is > By fetching all set entries we can then fetch all elements, which is
> automated in this function. > automated in this function.
> For example modules of the same group, e.g. action modules are registered in an > For example, modules of the same group, e.g. action invokers are registered in an
> unordered set in the database, from where they can be retrieved again. For example > unordered set in the database, from where they can be retrieved again. For example
> a new action module has its ID (e.g 'probinder') first registered in the set > a new action invoker has its ID (e.g 'probinder') first registered in the set
> 'action_modules' and then stored in the db with the key 'action\_module\_' + ID > 'action-invokers' and then stored in the db with the key 'action-invoker:' + ID
> (e.g. action\_module\_probinder). > (e.g. action-invoker:probinder).
> >
*/ */
(function() { (function() {
var crypto, decrypt, encrypt, exports, getSetRecords, hash, log, redis, replyHandler, var IndexedModules, crypto, decrypt, encrypt, exports, getSetRecords, hash, log, redis, replyHandler,
_this = this; _this = this,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
log = require('./logging'); log = require('./logging');
@ -54,10 +55,12 @@ DB Interface
_this.db = redis.createClient(config.getDBPort(), 'localhost', { _this.db = redis.createClient(config.getDBPort(), 'localhost', {
connect_timeout: 2000 connect_timeout: 2000
}); });
return _this.db.on('error', function(err) { _this.db.on('error', function(err) {
err.addInfo = 'message from DB'; err.addInfo = 'message from DB';
return log.error('DB', err); return log.error('DB', err);
}); });
_this.ep = new IndexedModules('event-poller', _this.db);
return _this.ai = new IndexedModules('action-invoker', _this.db);
} else { } else {
return log.error('DB', 'Initialization failed because of missing config file!'); return log.error('DB', 'Initialization failed because of missing config file!');
} }
@ -103,7 +106,7 @@ DB Interface
replyHandler = function(action) { replyHandler = function(action) {
return function(err, reply) { return function(err, reply) {
if (err) { if (err) {
err.addInfo = "during \"" + action + "\""; err.addInfo = "during '" + action + "'";
return log.error('DB', err); return log.error('DB', err);
} else { } else {
return log.print('DB', "" + action + ": " + reply); return log.print('DB', "" + action + ": " + reply);
@ -121,7 +124,7 @@ DB Interface
exports.pushEvent = function(oEvent) { exports.pushEvent = function(oEvent) {
if (oEvent) { if (oEvent) {
log.print('DB', "Event pushed into the queue: " + oEvent.eventid); log.print('DB', "Event pushed into the queue: '" + oEvent.eventid + "'");
return _this.db.rpush('event_queue', JSON.stringify(oEvent)); return _this.db.rpush('event_queue', JSON.stringify(oEvent));
} else { } else {
return log.error('DB', 'Why would you give me an empty event...'); return log.error('DB', 'Why would you give me an empty event...');
@ -129,7 +132,7 @@ DB Interface
}; };
/* /*
Pop an event from the event queue and pass it to the callback(err, obj) function. Pop an event from the event queue and pass it to cb(err, obj).
@public popEvent( *cb* ) @public popEvent( *cb* )
@param {function} cb @param {function} cb
@ -191,14 +194,12 @@ DB Interface
encrypt = function(plainText) { encrypt = function(plainText) {
var enciph, err, et; var err;
if (plainText == null) { if (plainText == null) {
return null; return null;
} }
try { try {
enciph = crypto.createCipher('aes-256-cbc', _this.crypto_key); return crypto.AES.encrypt(plainText, _this.crypto_key);
et = enciph.update(plainText, 'utf8', 'base64');
return et + enciph.final('base64');
} catch (_error) { } catch (_error) {
err = _error; err = _error;
err.addInfo = 'during encryption'; err.addInfo = 'during encryption';
@ -216,14 +217,13 @@ DB Interface
decrypt = function(crypticText) { decrypt = function(crypticText) {
var deciph, dt, err; var dec, err;
if (crypticText == null) { if (crypticText == null) {
return null; return null;
} }
try { try {
deciph = crypto.createDecipher('aes-256-cbc', _this.crypto_key); dec = crypto.AES.decrypt(crypticText, _this.crypto_key);
dt = deciph.update(crypticText, 'base64', 'utf8'); return dec.toString(crypto.enc.Utf8);
return dt + deciph.final('utf8');
} catch (_error) { } catch (_error) {
err = _error; err = _error;
err.addInfo = 'during decryption'; err.addInfo = 'during decryption';
@ -233,23 +233,26 @@ DB Interface
}; };
/* /*
Fetches all linked data set keys from a linking set, fetches the single data objects Fetches all linked data set keys from a linking set, fetches the single
via the provided function and returns the results to the callback(err, obj) function. data objects via the provided function and returns the results to cb(err, obj).
@private getSetRecords( *set, fSingle, cb* ) @private getSetRecords( *set, fSingle, cb* )
@param {String} set the set name how it is stored in the DB @param {String} set the set name how it is stored in the DB
@param {function} fSingle a function to retrieve a single data element per set entry @param {function} fSingle a function to retrieve a single data element
@param {function} cb the callback(err, obj) function that receives all the retrieved data or an error per set entry
@param {function} cb the callback(err, obj) function that receives all
the retrieved data or an error
*/ */
getSetRecords = function(set, fSingle, cb) { getSetRecords = function(set, fSingle, cb) {
log.print('DB', "Fetching set records: " + set); log.print('DB', "Fetching set records: '" + set + "'");
return _this.db.smembers(set, function(err, arrReply) { return _this.db.smembers(set, function(err, arrReply) {
var fCallback, objReplies, reply, semaphore, _i, _len, _results; var fCallback, objReplies, reply, semaphore, _i, _len, _results;
if (err) { if (err) {
err.addInfo = "fetching " + set; err.addInfo = "fetching '" + set + "'";
return log.error('DB', err); log.error('DB', err);
return cb(err);
} else if (arrReply.length === 0) { } else if (arrReply.length === 0) {
return cb(); return cb();
} else { } else {
@ -257,17 +260,17 @@ DB Interface
objReplies = {}; objReplies = {};
setTimeout(function() { setTimeout(function() {
if (semaphore > 0) { if (semaphore > 0) {
return cb(new Error("Timeout fetching " + set)); return cb(new Error("Timeout fetching '" + set + "'"));
} }
}, 2000); }, 2000);
fCallback = function(prop) { fCallback = function(prop) {
return function(err, data) { return function(err, data) {
--semaphore; --semaphore;
if (err) { if (err) {
err.addInfo = "fetching single element: " + prop; err.addInfo = "fetching single element: '" + prop + "'";
log.error('DB', err); log.error('DB', err);
} else if (!data) { } else if (!data) {
log.error('DB', new Error("Empty key in DB: " + prop)); log.error('DB', new Error("Empty key in DB: '" + prop + "'"));
} else { } else {
objReplies[prop] = data; objReplies[prop] = data;
} }
@ -286,192 +289,315 @@ DB Interface
}); });
}; };
IndexedModules = (function() {
function IndexedModules(setname, db) {
this.setname = setname;
this.db = db;
this.deleteParameters = __bind(this.deleteParameters, this);
this.getParametersIds = __bind(this.getParametersIds, this);
this.getParameters = __bind(this.getParameters, this);
this.storeParameters = __bind(this.storeParameters, this);
this.deleteModule = __bind(this.deleteModule, this);
this.getModules = __bind(this.getModules, this);
this.getModuleIds = __bind(this.getModuleIds, this);
this.getModule = __bind(this.getModule, this);
this.storeModule = __bind(this.storeModule, this);
log.print('DB', "Instantiated indexed modules for '" + this.setname + "'");
}
IndexedModules.prototype.storeModule = function(mId, data) {
log.print('DB', "storeModule(" + this.setname + "): " + mId);
this.db.sadd("" + this.setname + "s", mId, replyHandler("Storing '" + this.setname + "' key '" + mId + "'"));
return this.db.set("" + this.setname + ":" + mId, data, replyHandler("Storing '" + this.setname + ":" + mId + "'"));
};
IndexedModules.prototype.getModule = function(mId, cb) {
log.print('DB', "getModule('" + this.setname + "): " + mId + "'");
return this.db.get("" + this.setname + ":" + mId, cb);
};
IndexedModules.prototype.getModuleIds = function(cb) {
log.print('DB', "getModuleIds(" + this.setname + ")");
return this.db.smembers("" + this.setname + "s", cb);
};
IndexedModules.prototype.getModules = function(cb) {
log.print('DB', "getModules(" + this.setname + ")");
return getSetRecords("" + this.setname + "s", this.getModule, cb);
};
IndexedModules.prototype.deleteModule = function(mId) {
log.print('DB', "deleteModule(" + this.setname + "): " + mId);
this.db.srem("" + this.setname + "s", mId, replyHandler("Deleting '" + this.setname + "' key '" + mId + "'"));
return this.db.del("" + this.setname + ":" + mId, replyHandler("Deleting '" + this.setname + ":" + mId + "'"));
};
IndexedModules.prototype.storeParameters = function(mId, userId, data) {
log.print('DB', "storeParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
this.db.sadd("" + this.setname + "-params", "" + mId + ":" + userId, replyHandler("Storing '" + this.setname + "' module parameters key '" + mId + "'"));
return this.db.set("" + this.setname + "-params:" + mId + ":" + userId, encrypt(data), replyHandler("Storing '" + this.setname + "' module parameters '" + mId + ":" + userId + "'"));
};
IndexedModules.prototype.getParameters = function(mId, userId, cb) {
log.print('DB', "getParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
return this.db.get("" + this.setname + "-params:" + mId + ":" + userId, function(err, data) {
return cb(err, decrypt(data));
});
};
IndexedModules.prototype.getParametersIds = function(cb) {
log.print('DB', "getParametersIds(" + this.setname + ")");
return this.db.smembers("" + this.setname + "-params", cb);
};
IndexedModules.prototype.deleteParameters = function(mId, userId) {
log.print('DB', "deleteParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
this.db.srem("" + this.setname + "-params", "" + mId + ":" + userId, replyHandler("Deleting '" + this.setname + "-params' key '" + mId + ":" + userId + "'"));
return this.db.del("" + this.setname + "-params:" + mId + ":" + userId, replyHandler("Deleting '" + this.setname + "-params:" + mId + ":" + userId + "'"));
};
return IndexedModules;
})();
/* /*
## Action Modules ## Action Invokers
#TODO Rename Action Modules into something like Action Caller
*/ */
/* /*
Store a string representation of an action module in the DB. Store a string representation of an action invoker in the DB.
@public storeActionModule ( *amId, data* ) @public storeActionInvoker ( *aiId, data* )
@param {String} amId @param {String} aiId
@param {String} data @param {String} data
*/ */
exports.storeActionModule = function(amId, data) { exports.storeActionInvoker = function(aiId, data) {
log.print('DB', "storeActionModule: " + amId); return _this.ai.storeModule(aiId, data);
_this.db.sadd('action-modules', amId, replyHandler("storing action module key " + amId));
return _this.db.set("action-module:" + amId, data, replyHandler("storing action module " + amId));
}; };
/* /*
Query the DB for an action module and pass it to the callback(err, obj) function. Query the DB for an action invoker and pass it to cb(err, obj).
@public getActionModule( *amId, cb* ) @public getActionInvoker( *aiId, cb* )
@param {String} amId @param {String} aiId
@param {function} cb @param {function} cb
*/ */
exports.getActionModule = function(amId, cb) { exports.getActionInvoker = function(aiId, cb) {
log.print('DB', "getActionModule: " + amId); return _this.ai.getModule(aiId, cb);
return _this.db.get("action-module:" + amId, cb);
};
exports.getSetMembers = function(setId, cb) {
return _this.db.smembers(setId, cb);
}; };
/* /*
Fetch all action module IDs and hand them to the callback(err, obj) function. Fetch all action invoker IDs and hand them to cb(err, obj).
@public getActionModuleIds( *cb* ) @public getActionInvokerIds( *cb* )
@param {function} cb @param {function} cb
*/ */
exports.getActionModuleIds = function(cb) { exports.getActionInvokerIds = function(cb) {
return _this.db.smembers('action-modules', cb); return _this.ai.getModuleIds(cb);
}; };
/* /*
Fetch all action modules and hand them to the callback(err, obj) function. Fetch all action invokers and hand them to cb(err, obj).
@public getActionModules( *cb* ) @public getActionInvokers( *cb* )
@param {function} cb @param {function} cb
*/ */
exports.getActionModules = function(cb) { exports.getActionInvokers = function(cb) {
return getSetRecords('action-modules', exports.getActionModule, cb); return _this.ai.getModules(cb);
}; };
/* /*
Fetch all action modules and hand them to the callback(err, obj) function. Fetch all action invokers and hand them to cb(err, obj).
@public getActionModules( *cb* ) @public getActionInvokers( *cb* )
@param {function} cb @param {function} cb
*/ */
exports.deleteActionModule = function(amId) { exports.deleteActionInvoker = function(aiId) {
_this.db.srem('action-modules', amId, replyHandler("deleting action module key " + amId)); return _this.ai.deleteModule(aiId);
return _this.db.del("action-module:" + amId, replyHandler("deleting action module " + amId));
}; };
/* /*
Store user-specific action module parameters . Store user-specific action invoker parameters .
@public storeActionParams( *userId, amId, data* ) @public storeActionParams( *userId, aiId, data* )
@param {String} userId @param {String} userId
@param {String} amId @param {String} aiId
@param {String} data @param {String} data
*/ */
exports.storeActionParams = function(userId, amId, data) { exports.storeActionParams = function(aiId, userId, data) {
log.print('DB', "storeActionParams: " + amId + ":" + userId); return _this.ai.storeParameters(aiId, userId, data);
return _this.db.set("action-params:" + amId + ":" + userId, hash(data), replyHandler("storing action params " + amId + ":" + userId));
}; };
/* /*
Query the DB for user-specific action module parameters, Query the DB for user-specific action module parameters,
and pass it to the callback(err, obj) function. and pass it to cb(err, obj).
@public getActionParams( *userId, amId, cb* ) @public getActionParams( *userId, aiId, cb* )
@param {String} userId @param {String} userId
@param {String} amId @param {String} aiId
@param {function} cb @param {function} cb
*/ */
exports.getActionParams = function(userId, amId, cb) { exports.getActionParams = function(aiId, userId, cb) {
log.print('DB', "getActionParams: " + amId + ":" + userId); return _this.ai.getParameters(aiId, userId, cb);
return _this.db.get("action-params:" + amId + ":" + userId, function(err, data) {
return cb(err, decrypt(data));
});
}; };
/* /*
## Event Modules Fetch all action params IDs and hand them to cb(err, obj).
#TODO rename event modules to event puller or something like that
@public getActionParamsIds( *cb* )
@param {function} cb
*/
exports.getActionParamsIds = function(cb) {
return _this.ai.getParametersIds(cb);
};
/*
Fetch all action modules and hand them to cb(err, obj).
@public deleteActionParams( *cb* )
@param {function} cb
*/
exports.deleteActionParams = function(aiId, userId) {
return _this.ai.deleteParameters(aiId, userId);
};
/*
## Event Pollers
*/ */
/* /*
Store a string representation of an event module in the DB. Store a string representation of an event poller in the DB.
@public storeEventModule( *emId, data* ) @public storeEventPoller ( *epId, data* )
@param {String} emId @param {String} epId
@param {String} data @param {String} data
*/ */
exports.storeEventModule = function(emId, data) { exports.storeEventPoller = function(epId, data) {
log.print('DB', "storeEventModule: " + emId); return _this.ep.storeModule(epId, data);
_this.db.sadd('event-modules', emId, replyHandler("storing event module key " + emId));
return _this.db.set('event-module:#{ emId }', data, replyHandler("storing event module " + emId));
}; };
/* /*
Query the DB for an event module and pass it to the callback(err, obj) function. Query the DB for an event poller and pass it to cb(err, obj).
@public getEventModule( *emId, cb* ) @public getEventPoller( *epId, cb* )
@param {String} emId @param {String} epId
@param {function} cb @param {function} cb
*/ */
exports.getEventModule = function(emId, cb) { exports.getEventPoller = function(epId, cb) {
log.print('DB', "getEventModule: " + emId); return _this.ep.getModule(epId, cb);
return _this.db.get("event-module:" + emId, cb);
}; };
/* /*
Fetch all event modules and pass them to the callback(err, obj) function. Fetch all event poller IDs and hand them to cb(err, obj).
@public getEventModules( *cb* ) @public getEventPollerIds( *cb* )
@param {function} cb @param {function} cb
*/ */
exports.getEventModules = function(cb) { exports.getEventPollerIds = function(cb) {
return getSetRecords('event-modules', exports.getEventModule, cb); return _this.ep.getModuleIds(cb);
}; };
/* /*
Store a string representation of user-specific parameters for an event module. Fetch all event pollers and hand them to cb(err, obj).
@public storeEventParams( *userId, emId, data* ) @public getEventPollers( *cb* )
@param {function} cb
*/
exports.getEventPollers = function(cb) {
return _this.ep.getModules(cb);
};
/*
Fetch all event pollers and hand them to cb(err, obj).
@public getEventPollers( *cb* )
@param {function} cb
*/
exports.deleteEventPoller = function(epId) {
return _this.ep.deleteModule(epId);
};
/*
Store user-specific event poller parameters .
@public storeEventParams( *userId, epId, data* )
@param {String} userId @param {String} userId
@param {String} emId @param {String} epId
@param {Object} data @param {String} data
*/ */
exports.storeEventParams = function(userId, emId, data) { exports.storeEventParams = function(epId, userId, data) {
log.print('DB', "storeEventParams: " + emId + ":" + userId); return _this.ep.storeParameters(epId, userId, data);
return _this.db.set("event-params:" + emId + ":" + userId, encrypt(data), replyHandler("storing event auth " + emId + ":" + userId));
}; };
/* /*
Query the DB for an action module authentication token, associated with a user. Query the DB for user-specific event module parameters,
and pass it to cb(err, obj).
@public getEventAuth( *userId, emId, data* ) @public getEventParams( *userId, epId, cb* )
@param {String} userId @param {String} userId
@param {String} emId @param {String} epId
@param {function} cb @param {function} cb
*/ */
exports.getEventAuth = function(userId, emId, cb) { exports.getEventParams = function(epId, userId, cb) {
log.print('DB', "getEventAuth: " + emId + ":" + userId); return _this.ep.getParameters(epId, userId, cb);
return _this.db.get("event-auth:" + emId + ":" + userId, function(err, data) { };
return cb(err, decrypt(data));
}); /*
Fetch all event params IDs and hand them to cb(err, obj).
@public getEventParamsIds( *cb* )
@param {function} cb
*/
exports.getEventParamsIds = function(cb) {
return _this.ep.getParametersIds(cb);
};
/*
Fetch all event modules and hand them to cb(err, obj).
@public deleteEventParams( *cb* )
@param {function} cb
*/
exports.deleteEventParams = function(epId, userId) {
return _this.ep.deleteParameters(epId, userId);
}; };
/* /*
@ -480,25 +606,7 @@ DB Interface
/* /*
Store a string representation of a rule in the DB. Query the DB for a rule and pass it to cb(err, obj).
@public storeRule( *ruleId, userId, data* )
@param {String} ruleId
@param {String} userId
@param {String} data
*/
exports.storeRule = function(ruleId, userId, data) {
log.print('DB', "storeRule: " + ruleId);
_this.db.sadd('rules', "" + ruleId + ":" + userId, replyHandler("storing rule key \"" + ruleId + ":" + userId + "\""));
_this.db.sadd("user-set:" + userId + ":rules", ruleId, replyHandler("storing rule key to \"user:" + userId + ":rules\""));
_this.db.sadd("rule-set:" + ruleId + ":users", user, replyHandler("storing user key to \"rule:" + ruleId + ":users\""));
return _this.db.set("rule:" + ruleId + ":" + userId, data, replyHandler("storing rule \"" + ruleId + ":" + userId + "\""));
};
/*
Query the DB for a rule and pass it to the callback(err, obj) function.
@public getRule( *ruleId, cb* ) @public getRule( *ruleId, cb* )
@param {String} ruleId @param {String} ruleId
@ -507,12 +615,12 @@ DB Interface
exports.getRule = function(ruleId, cb) { exports.getRule = function(ruleId, cb) {
log.print('DB', "getRule: " + ruleId); log.print('DB', "getRule: '" + ruleId + "'");
return _this.db.get("rule:" + ruleId, cb); return _this.db.get("rule:" + ruleId, cb);
}; };
/* /*
Fetch all rules from the database and pass them to the callback function. Fetch all rules and pass them to cb(err, obj).
@public getRules( *cb* ) @public getRules( *cb* )
@param {function} cb @param {function} cb
@ -524,6 +632,262 @@ DB Interface
return getSetRecords('rules', exports.getRule, cb); return getSetRecords('rules', exports.getRule, cb);
}; };
/*
Fetch all rule IDs and hand it to cb(err, obj).
@public getRuleIds( *cb* )
@param {function} cb
*/
exports.getRuleIds = function(cb) {
log.print('DB', 'Fetching all Rule IDs');
return _this.db.smembers('rules', cb);
};
/*
Store a string representation of a rule in the DB.
@public storeRule( *ruleId, data* )
@param {String} ruleId
@param {String} data
*/
exports.storeRule = function(ruleId, data) {
log.print('DB', "storeRule: '" + ruleId + "'");
_this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'"));
return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'"));
};
/*
Delete a string representation of a rule.
@public deleteRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
*/
exports.deleteRule = function(ruleId) {
log.print('DB', "deleteRule: '" + ruleId + "'");
_this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'"));
_this.db.del("rule:" + ruleId, replyHandler("Deleting 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 + "'"));
};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
id = obj[_i];
_results.push(delLinkedUserRule(id));
}
return _results;
});
_this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting 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 + "'"));
};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
id = obj[_i];
_results.push(delActiveUserRule(id));
}
return _results;
});
return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users"));
};
/*
Associate a rule to a user.
@public linkRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
*/
exports.linkRule = function(ruleId, userId) {
log.print('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 + "'"));
};
/*
Get rules linked to a user and hand it to cb(err, obj).
@public getUserLinkRule( *userId, cb* )
@param {String} userId
@param {function} cb
*/
exports.getUserLinkedRules = function(userId, cb) {
log.print('DB', "getUserLinkedRules: for user '" + userId + "'");
return _this.db.smembers("user:" + userId + ":rules", cb);
};
/*
Get users linked to a rule and hand it to cb(err, obj).
@public getRuleLinkedUsers( *ruleId, cb* )
@param {String} ruleId
@param {function} cb
*/
exports.getRuleLinkedUsers = function(ruleId, cb) {
log.print('DB', "getRuleLinkedUsers: for rule '" + ruleId + "'");
return _this.db.smembers("rule:" + ruleId + ":users", cb);
};
/*
Delete an association of a rule to a user.
@public unlinkRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
*/
exports.unlinkRule = function(ruleId, userId) {
log.print('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 + "'"));
};
/*
Activate a rule.
@public activateRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
*/
exports.activateRule = function(ruleId, userId) {
log.print('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 + "'"));
};
/*
Get rules activated for a user and hand it to cb(err, obj).
@public getUserLinkRule( *userId, cb* )
@param {String} userId
@param {function} cb
*/
exports.getUserActivatedRules = function(userId, cb) {
log.print('DB', "getUserActivatedRules: for user '" + userId + "'");
return _this.db.smembers("user:" + userId + ":active-rules", cb);
};
/*
Get users activated for a rule and hand it to cb(err, obj).
@public getRuleActivatedUsers ( *ruleId, cb* )
@param {String} ruleId
@param {function} cb
*/
exports.getRuleActivatedUsers = function(ruleId, cb) {
log.print('DB', "getRuleLinkedUsers: for rule '" + ruleId + "'");
return _this.db.smembers("rule:" + ruleId + ":active-users", cb);
};
/*
Deactivate a rule.
@public deactivateRule( *ruleId, userId* )
@param {String} ruleId
@param {String} userId
*/
exports.deactivateRule = function(ruleId, userId) {
log.print('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 + "'"));
};
/*
Fetch all active ruleIds and pass them to cb(err, obj).
@public getAllActivatedRuleIds( *cb* )
@param {function} cb
*/
exports.getAllActivatedRuleIdsPerUser = function(cb) {
log.print('DB', "Fetching all active rules");
return _this.db.smembers('users', function(err, obj) {
var fFetchActiveUserRules, result, semaphore, user, _i, _len, _results;
result = {};
console.log('checking length');
if (obj.length === 0) {
console.log('length cehcked is 0');
return cb(null, result);
} else {
console.log('length cehcked');
semaphore = obj.length;
fFetchActiveUserRules = function(userId) {
return _this.db.smembers("user:" + user + ":active-rules", function(err, obj) {
console.log(obj);
console.log(obj.length);
if (obj.length === 0) {
console.log('is 0');
} else {
result[userId] = obj;
}
if (--semaphore === 0) {
return cb(null, result);
}
});
};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
user = obj[_i];
_results.push(fFetchActiveUserRules(user));
}
return _results;
}
});
};
/*
Fetch all active rules and pass them to cb(err, obj).
@public getAllActivatedRules( *cb* )
@param {function} cb
*/
exports.getAllActivatedRules = function(cb) {
var fCb;
log.print('DB', "Fetching all active rules");
fCb = function(err, obj) {
console.log('fetched something');
console.log(err);
return console.log(obj);
};
return _this.db.smembers('users', function(err, obj) {
var user, _i, _len, _results;
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
user = obj[_i];
_results.push(getSetRecords("user:" + user + ":active-rules", exports.getRule, fCb));
}
return _results;
});
};
/* /*
Store a user object (needs to be a flat structure). Store a user object (needs to be a flat structure).
@ -533,11 +897,11 @@ DB Interface
exports.storeUser = function(objUser) { exports.storeUser = function(objUser) {
log.print('DB', "storeUser: " + objUser.username); log.print('DB', "storeUser: '" + objUser.username + "'");
if (objUser && objUser.username && objUser.password) { if (objUser && objUser.username && objUser.password) {
_this.db.sadd('users', objUser.username, replyHandler("storing user key " + objUser.username)); _this.db.sadd('users', objUser.username, replyHandler("storing user key '" + objUser.username + "'"));
objUser.password = hash(objUser.password); objUser.password = hash(objUser.password);
return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties " + objUser.username)); return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties '" + objUser.username + "'"));
} else { } else {
return log.error('DB', new Error('username or password was missing')); return log.error('DB', new Error('username or password was missing'));
} }
@ -553,14 +917,14 @@ DB Interface
exports.storeUserRole = function(userId, role) { exports.storeUserRole = function(userId, role) {
log.print('DB', "storeUserRole: " + userId + ":" + role); log.print('DB', "storeUserRole: '" + userId + ":" + role + "'");
_this.db.sadd('roles', role, replyHandler("adding role " + role + " to role index set")); _this.db.sadd('roles', role, replyHandler("adding role '" + role + "' to role index set"));
_this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role " + role + " to user " + userId)); _this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role '" + role + "' to user '" + userId + "'"));
return _this.db.sadd("role:" + role + ":users", userId, replyHandler("adding user " + userId + " to role " + role)); return _this.db.sadd("role:" + role + ":users", userId, replyHandler("adding user '" + userId + "' to role '" + role + "'"));
}; };
/* /*
Fetch all roles of a user and pass them to the callback(err, obj) Fetch all roles of a user and pass them to cb(err, obj).
@public getUserRoles( *userId* ) @public getUserRoles( *userId* )
@param {String} userId @param {String} userId
@ -568,12 +932,12 @@ DB Interface
exports.getUserRoles = function(userId) { exports.getUserRoles = function(userId) {
log.print('DB', "getUserRole: " + userId); log.print('DB', "getUserRole: '" + userId + "'");
return _this.db.get("user-roles:" + userId, cb); return _this.db.get("user-roles:" + userId, cb);
}; };
/* /*
Fetch all users of a role and pass them to the callback(err, obj) Fetch all users of a role and pass them to cb(err, obj).
@public getUserRoles( *role* ) @public getUserRoles( *role* )
@param {String} role @param {String} role
@ -581,7 +945,7 @@ DB Interface
exports.getRoleUsers = function(role) { exports.getRoleUsers = function(role) {
log.print('DB', "getRoleUsers: " + role); log.print('DB', "getRoleUsers: '" + role + "'");
return _this.db.get("role-users:" + role, cb); return _this.db.get("role-users:" + role, cb);
}; };
@ -600,14 +964,14 @@ DB Interface
exports.loginUser = function(userId, password, cb) { exports.loginUser = function(userId, password, cb) {
var fCheck; var fCheck;
log.print('DB', "User \"" + userId + "\" tries to log in"); log.print('DB', "User '" + userId + "' tries to log in");
fCheck = function(pw) { fCheck = function(pw) {
return function(err, obj) { return function(err, obj) {
if (err) { if (err) {
return cb(err); return cb(err);
} else if (obj && obj.password) { } else if (obj && obj.password) {
if (pw === obj.password) { if (pw === obj.password) {
log.print('DB', "User \"" + obj.username + "\" logged in!"); log.print('DB', "User '" + obj.username + "' logged in!");
return cb(null, obj); return cb(null, obj);
} else { } else {
return cb(new Error('Wrong credentials!')); return cb(new Error('Wrong credentials!'));
@ -620,6 +984,46 @@ DB Interface
return _this.db.hgetall("user:" + userId, fCheck(password)); return _this.db.hgetall("user:" + userId, fCheck(password));
}; };
/*
Deletes a user and all his associated linked and active rules.
@public deleteUser( *userId* )
@param {String} userId
*/
exports.deleteUser = function(userId) {
log.print('DB', "deleteUser: '" + userId + "'");
_this.db.srem("users", userId, replyHandler("Deleting user key '" + userId + "'"));
_this.db.del("user:" + userId, replyHandler("Deleting user '" + userId + "'"));
_this.db.smembers("user:" + userId + ":rules", function(err, obj) {
var delLinkedRuleUser, id, _i, _len, _results;
delLinkedRuleUser = function(ruleId) {
return _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in linked rule '" + ruleId + "'"));
};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
id = obj[_i];
_results.push(delLinkedRuleUser(id));
}
return _results;
});
_this.db.del("user:" + userId + ":rules", replyHandler("Deleting user '" + userId + "' rules"));
_this.db.smembers("user:" + userId + ":rules", function(err, obj) {
var delActivatedRuleUser, id, _i, _len, _results;
delActivatedRuleUser = function(ruleId) {
return _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("Deleting user key '" + userId + "' in active rule '" + ruleId + "'"));
};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
id = obj[_i];
_results.push(delActivatedRuleUser(id));
}
return _results;
});
return _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules"));
};
/* /*
Shuts down the db link. Shuts down the db link.

View file

@ -29,34 +29,34 @@ exports = module.exports = function(args) {
*/ */
exports.addDBLinkAndLoadActionsAndRules = function(db_link) { exports.addDBLinkAndLoadActionsAndRules = function(db_link) {
db = db_link; db = db_link;
if(ml && db) db.getActionModules(function(err, obj) { // if(ml && db) db.getActionModules(function(err, obj) {
if(err) log.error('EN', 'retrieving Action Modules from DB!'); // if(err) log.error('EN', 'retrieving Action Modules from DB!');
else { // else {
if(!obj) { // if(!obj) {
log.print('EN', 'No Action Modules found in DB!'); // log.print('EN', 'No Action Modules found in DB!');
loadRulesFromDB(); // loadRulesFromDB();
} else { // } else {
var m; // var m;
for(var el in obj) { // for(var el in obj) {
log.print('EN', 'Loading Action Module from DB: ' + el); // log.print('EN', 'Loading Action Module from DB: ' + el);
try{ // try{
m = ml.requireFromString(obj[el], el); // m = ml.requireFromString(obj[el], el);
db.getActionModuleAuth(el, function(mod) { // db.getActionModuleAuth(el, function(mod) {
return function(err, obj) { // return function(err, obj) {
if(obj && mod.loadCredentials) mod.loadCredentials(JSON.parse(obj)); // if(obj && mod.loadCredentials) mod.loadCredentials(JSON.parse(obj));
}; // };
}(m)); // }(m));
listActionModules[el] = m; // listActionModules[el] = m;
} catch(e) { // } catch(e) {
e.addInfo = 'error in action module "' + el + '"'; // e.addInfo = 'error in action module "' + el + '"';
log.error('EN', e); // log.error('EN', e);
} // }
} // }
loadRulesFromDB(); // loadRulesFromDB();
} // }
} // }
}); // });
else log.severe('EN', new Error('Module Loader or DB not defined!')); // else log.severe('EN', new Error('Module Loader or DB not defined!'));
}; };
function loadRulesFromDB() { function loadRulesFromDB() {

View file

@ -8,7 +8,7 @@ Request Handler
(function() { (function() {
var answerHandler, crypto, db, exports, fs, getHandlerFileAsString, getHandlerPath, log, mm, mustache, objAdminCmds, objUserCmds, path, qs, renderPage, sendLoginOrPage, var answerHandler, crypto, db, exports, fs, getHandlerFileAsString, getHandlerPath, getIncludeFileAsString, log, mm, mustache, objAdminCmds, objUserCmds, path, qs, renderPage, sendLoginOrPage,
_this = this; _this = this;
log = require('./logging'); log = require('./logging');
@ -189,6 +189,20 @@ Request Handler
return fs.readFileSync(getHandlerPath(name), 'utf8'); return fs.readFileSync(getHandlerPath(name), 'utf8');
}; };
/*
Fetches an include file.
@private getIncludeFileAsString( *name* )
@param {String} name
*/
getIncludeFileAsString = function(name) {
var pth;
pth = path.resolve(__dirname, '..', 'webpages', 'handlers', 'includes', name + '.html');
return fs.readFileSync(pth, 'utf8');
};
/* /*
Renders a page depending on the user session and returns it. Renders a page depending on the user session and returns it.
@ -201,8 +215,8 @@ Request Handler
renderPage = function(name, sess, msg) { renderPage = function(name, sess, msg) {
var menubar, requires, template, view; var menubar, requires, template, view;
template = getHandlerFileAsString(name); template = getHandlerFileAsString(name);
menubar = getHandlerFileAsString('part_menubar'); menubar = getIncludeFileAsString('menubar');
requires = getHandlerFileAsString('part_requires'); requires = getIncludeFileAsString('requires');
view = { view = {
user: sess.user, user: sess.user,
head_requires: requires, head_requires: requires,
@ -226,11 +240,13 @@ Request Handler
sendLoginOrPage = function(pagename, req, resp) { sendLoginOrPage = function(pagename, req, resp) {
if (req.session && req.session.user) { if (!req.session) {
return resp.send(renderPage(pagename, req.session)); req.session = {};
} else {
return resp.sendfile(getHandlerPath('login'));
} }
if (!req.session.user) {
pagename = 'login';
}
return resp.send(renderPage(pagename, req.session));
}; };
/* /*

View file

@ -31,7 +31,7 @@
exports.testDifferentConfigFile = function(test) { exports.testDifferentConfigFile = function(test) {
test.expect(1); test.expect(1);
_this.conf({ _this.conf({
configPath: 'testing/jsonWrongConfig.json' configPath: path.join('testing', 'files', 'jsonWrongConfig.json')
}); });
test.ok(_this.conf.isReady(), 'Different path not loaded!'); test.ok(_this.conf.isReady(), 'Different path not loaded!');
return test.done(); return test.done();

View file

@ -4,7 +4,6 @@
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
exports.setUp = function(cb) { exports.setUp = function(cb) {
_this.log = require('../js-coffee/logging');
_this.db = require('../js-coffee/db_interface'); _this.db = require('../js-coffee/db_interface');
_this.db({ _this.db({
logType: 2 logType: 2
@ -47,11 +46,11 @@
}, },
testPurgeQueue: function(test) { testPurgeQueue: function(test) {
var evt; var evt;
test.expect(2);
evt = { evt = {
eventid: '1', eventid: '1',
event: 'mail' event: 'mail'
}; };
test.expect(2);
_this.db.pushEvent(evt); _this.db.pushEvent(evt);
_this.db.purgeEventQueue(); _this.db.purgeEventQueue();
return _this.db.popEvent(function(err, obj) { return _this.db.popEvent(function(err, obj) {
@ -128,68 +127,435 @@
} }
}; };
exports.action_modules = { exports.action_invoker = {
testModule: function(test) { testCreateAndRead: function(test) {
var action1, action1name, fCheckModuleExists, fCheckModuleNotExists, fCheckModuleNotExistsInSet, fCheckSetEntry; var action, id;
test.expect(4);
action1name = 'test-action-module_1';
action1 = 'unit-test action module 1 content';
fCheckSetEntry = function(err, obj) {
test.ok(__indexOf.call(obj, action1name) >= 0, 'Expected key not in action-modules set');
return _this.db.getActionModule(action1name, fCheckModuleExists);
};
fCheckModuleExists = function(err, obj) {
test.strictEqual(obj, action1, 'Retrieved Action Module is not what we expected');
_this.log.print('delete action module');
_this.db.deleteActionModule(action1name);
_this.log.print('tried to delete action module');
return _this.db.getActionModule(action1name, fCheckModuleNotExists);
};
fCheckModuleNotExists = function(err, obj) {
_this.log.print('got action module');
test.strictEqual(obj, null, 'Action module still exists');
_this.log.print('compared action module');
return _this.db.getActionModuleIds(fCheckModuleNotExistsInSet);
};
fCheckModuleNotExistsInSet = function(err, obj) {
test.ok(__indexOf.call(obj, action1name) < 0, 'Action module key still exists in set');
return test.done();
};
_this.db.storeActionModule(action1name, action1);
return _this.db.getActionModuleIds(fCheckSetEntry);
},
testFetchSeveralModules: function(test) {
var action1, action1name, action2, action2name, fCheckModule, fCheckSetEntries, forkEnds, semaphore;
semaphore = 2;
forkEnds = function() {
if (--semaphore === 0) {
return test.done();
}
};
test.expect(3); test.expect(3);
action1name = 'test-action-module_1'; id = 'test-action-invoker';
action2name = 'test-action-module_2'; action = 'unit-test action invoker content';
action1 = 'unit-test action module 1 content'; _this.db.storeActionInvoker(id, action);
action2 = 'unit-test action module 2 content'; return _this.db.getActionInvokerIds(function(err, obj) {
fCheckModule = function(mod) { test.ok(__indexOf.call(obj, id) >= 0, 'Expected key not in action-invokers set');
var myTest; return _this.db.getActionInvoker(id, function(err, obj) {
test.strictEqual(obj, action, 'Retrieved Action Invoker is not what we expected');
return _this.db.getActionInvokers(function(err, obj) {
test.deepEqual(action, obj[id], 'Action Invoker ist not in result set');
_this.db.deleteActionInvoker(id);
return test.done();
});
});
});
},
testUpdate: function(test) {
var action, actionNew, id;
test.expect(2);
id = 'test-action-invoker';
action = 'unit-test action invoker content';
actionNew = 'unit-test action invoker new content';
_this.db.storeActionInvoker(id, action);
_this.db.storeActionInvoker(id, actionNew);
return _this.db.getActionInvoker(id, function(err, obj) {
test.strictEqual(obj, actionNew, 'Retrieved Action Invoker is not what we expected');
return _this.db.getActionInvokers(function(err, obj) {
test.deepEqual(actionNew, obj[id], 'Action Invoker ist not in result set');
_this.db.deleteActionInvoker(id);
return test.done();
});
});
},
testDelete: function(test) {
var action, id;
test.expect(2);
id = 'test-action-invoker';
action = 'unit-test action invoker content';
_this.db.storeActionInvoker(id, action);
_this.db.deleteActionInvoker(id);
return _this.db.getActionInvoker(id, function(err, obj) {
test.strictEqual(obj, null, 'Action Invoker still exists');
return _this.db.getActionInvokerIds(function(err, obj) {
test.ok(__indexOf.call(obj, id) < 0, 'Action Invoker key still exists in set');
return test.done();
});
});
},
testFetchSeveral: function(test) {
var action1, action1name, action2, action2name, fCheckInvoker, semaphore;
test.expect(3);
semaphore = 2;
action1name = 'test-action-invoker_1';
action2name = 'test-action-invoker_2';
action1 = 'unit-test action invoker 1 content';
action2 = 'unit-test action invoker 2 content';
fCheckInvoker = function(modname, mod) {
var forkEnds, myTest;
myTest = test; myTest = test;
console.log('check module'); forkEnds = function() {
if (--semaphore === 0) {
return myTest.done();
}
};
return function(err, obj) { return function(err, obj) {
console.log('db answered'); myTest.strictEqual(mod, obj, "Invoker " + modname + " does not equal the expected one");
myTest.strictEqual(mod, obj, "Module does not equal the expected one"); _this.db.deleteActionInvoker(modname);
return forkEnds(); return forkEnds();
}; };
}; };
fCheckSetEntries = function(err, obj) { _this.db.storeActionInvoker(action1name, action1);
test.ok(__indexOf.call(obj, action1name) >= 0 && __indexOf.call(obj, action2name) >= 0, 'Not all action module Ids in set'); _this.db.storeActionInvoker(action2name, action2);
console.log('setentries fetched'); return _this.db.getActionInvokerIds(function(err, obj) {
this.db.getActionModule(action1name, fCheckModule(action1)); test.ok(__indexOf.call(obj, action1name) >= 0 && __indexOf.call(obj, action2name) >= 0, 'Not all action invoker Ids in set');
return this.db.getActionModule(action2name, fCheckModule(action2)); _this.db.getActionInvoker(action1name, fCheckInvoker(action1name, action1));
return _this.db.getActionInvoker(action2name, fCheckInvoker(action2name, action2));
});
}
};
exports.action_invoker_params = {
testCreateAndRead: function(test) {
var actionId, params, userId;
test.expect(2);
userId = 'tester1';
actionId = 'test-action-invoker_1';
params = 'shouldn\'t this be an object?';
_this.db.storeActionParams(actionId, userId, params);
return _this.db.getActionParamsIds(function(err, obj) {
var _ref;
test.ok((_ref = actionId + ':' + userId, __indexOf.call(obj, _ref) >= 0), 'Expected key not in action-params set');
return _this.db.getActionParams(actionId, userId, function(err, obj) {
test.strictEqual(obj, params, 'Retrieved action params is not what we expected');
_this.db.deleteActionParams(actionId, userId);
return test.done();
});
});
},
testUpdate: function(test) {
var actionId, params, paramsNew, userId;
test.expect(1);
userId = 'tester1';
actionId = 'test-action-invoker_1';
params = 'shouldn\'t this be an object?';
paramsNew = 'shouldn\'t this be a new object?';
_this.db.storeActionParams(actionId, userId, params);
_this.db.storeActionParams(actionId, userId, paramsNew);
return _this.db.getActionParams(actionId, userId, function(err, obj) {
test.strictEqual(obj, paramsNew, 'Retrieved action params is not what we expected');
_this.db.deleteActionParams(actionId, userId);
return test.done();
});
},
testDelete: function(test) {
var actionId, params, userId;
test.expect(2);
userId = 'tester1';
actionId = 'test-action-invoker_1';
params = 'shouldn\'t this be an object?';
_this.db.storeActionParams(actionId, userId, params);
_this.db.deleteActionParams(actionId, userId);
return _this.db.getActionParams(actionId, userId, function(err, obj) {
test.strictEqual(obj, null, 'Action params still exists');
return _this.db.getActionParamsIds(function(err, obj) {
var _ref;
test.ok((_ref = actionId + ':' + userId, __indexOf.call(obj, _ref) < 0), 'Action Params key still exists in set');
return test.done();
});
});
}
};
exports.event_poller = {
testCreateAndRead: function(test) {
var event, id;
test.expect(3);
id = 'test-event-poller';
event = 'unit-test event poller content';
_this.db.storeEventPoller(id, event);
return _this.db.getEventPollerIds(function(err, obj) {
test.ok(__indexOf.call(obj, id) >= 0, 'Expected key not in event-pollers set');
return _this.db.getEventPoller(id, function(err, obj) {
test.strictEqual(obj, event, 'Retrieved Event Poller is not what we expected');
return _this.db.getEventPollers(function(err, obj) {
test.deepEqual(event, obj[id], 'Event Poller ist not in result set');
_this.db.deleteEventPoller(id);
return test.done();
});
});
});
},
testUpdate: function(test) {
var event, eventNew, id;
test.expect(2);
id = 'test-event-poller';
event = 'unit-test event poller content';
eventNew = 'unit-test event poller new content';
_this.db.storeEventPoller(id, event);
_this.db.storeEventPoller(id, eventNew);
return _this.db.getEventPoller(id, function(err, obj) {
test.strictEqual(obj, eventNew, 'Retrieved Event Poller is not what we expected');
return _this.db.getEventPollers(function(err, obj) {
test.deepEqual(eventNew, obj[id], 'Event Poller ist not in result set');
_this.db.deleteEventPoller(id);
return test.done();
});
});
},
testDelete: function(test) {
var event, id;
test.expect(2);
id = 'test-event-poller';
event = 'unit-test event poller content';
_this.db.storeEventPoller(id, event);
_this.db.deleteEventPoller(id);
return _this.db.getEventPoller(id, function(err, obj) {
test.strictEqual(obj, null, 'Event Poller still exists');
return _this.db.getEventPollerIds(function(err, obj) {
test.ok(__indexOf.call(obj, id) < 0, 'Event Poller key still exists in set');
return test.done();
});
});
},
testFetchSeveral: function(test) {
var event1, event1name, event2, event2name, fCheckPoller, semaphore;
test.expect(3);
semaphore = 2;
event1name = 'test-event-poller_1';
event2name = 'test-event-poller_2';
event1 = 'unit-test event poller 1 content';
event2 = 'unit-test event poller 2 content';
fCheckPoller = function(modname, mod) {
var forkEnds, myTest;
myTest = test;
forkEnds = function() {
if (--semaphore === 0) {
return myTest.done();
}
};
return function(err, obj) {
myTest.strictEqual(mod, obj, "Invoker " + modname + " does not equal the expected one");
_this.db.deleteEventPoller(modname);
return forkEnds();
};
}; };
_this.db.storeActionModule(action1name, action1); _this.db.storeEventPoller(event1name, event1);
_this.db.storeActionModule(action2name, action2); _this.db.storeEventPoller(event2name, event2);
return _this.db.getActionModuleIds(fCheckSetEntries); return _this.db.getEventPollerIds(function(err, obj) {
test.ok(__indexOf.call(obj, event1name) >= 0 && __indexOf.call(obj, event2name) >= 0, 'Not all event poller Ids in set');
_this.db.getEventPoller(event1name, fCheckPoller(event1name, event1));
return _this.db.getEventPoller(event2name, fCheckPoller(event2name, event2));
});
}
};
exports.event_poller_params = {
testCreateAndRead: function(test) {
var eventId, params, userId;
test.expect(2);
userId = 'tester1';
eventId = 'test-event-poller_1';
params = 'shouldn\'t this be an object?';
_this.db.storeEventParams(eventId, userId, params);
return _this.db.getEventParamsIds(function(err, obj) {
var _ref;
test.ok((_ref = eventId + ':' + userId, __indexOf.call(obj, _ref) >= 0), 'Expected key not in event-params set');
return _this.db.getEventParams(eventId, userId, function(err, obj) {
test.strictEqual(obj, params, 'Retrieved event params is not what we expected');
_this.db.deleteEventParams(eventId, userId);
return test.done();
});
});
},
testUpdate: function(test) {
var eventId, params, paramsNew, userId;
test.expect(1);
userId = 'tester1';
eventId = 'test-event-poller_1';
params = 'shouldn\'t this be an object?';
paramsNew = 'shouldn\'t this be a new object?';
_this.db.storeEventParams(eventId, userId, params);
_this.db.storeEventParams(eventId, userId, paramsNew);
return _this.db.getEventParams(eventId, userId, function(err, obj) {
test.strictEqual(obj, paramsNew, 'Retrieved event params is not what we expected');
_this.db.deleteEventParams(eventId, userId);
return test.done();
});
},
testDelete: function(test) {
var eventId, params, userId;
test.expect(2);
userId = 'tester1';
eventId = 'test-event-poller_1';
params = 'shouldn\'t this be an object?';
_this.db.storeEventParams(eventId, userId, params);
_this.db.deleteEventParams(eventId, userId);
return _this.db.getEventParams(eventId, userId, function(err, obj) {
test.strictEqual(obj, null, 'Event params still exists');
return _this.db.getEventParamsIds(function(err, obj) {
var _ref;
test.ok((_ref = eventId + ':' + userId, __indexOf.call(obj, _ref) < 0), 'Event Params key still exists in set');
return test.done();
});
});
}
};
exports.rules = {
setUp: function(cb) {
_this.db({
logType: 1
});
_this.userId = 'tester-1';
_this.ruleId = 'test-rule_1';
_this.rule = {
"id": "rule_id",
"event": "custom",
"condition": {
"property": "yourValue"
},
"actions": []
};
_this.ruleNew = {
"id": "rule_new",
"event": "custom",
"condition": {
"property": "yourValue"
},
"actions": []
};
return cb();
},
tearDown: function(cb) {
_this.db.deleteRule(_this.ruleId);
return cb();
},
testCreateAndRead: function(test) {
test.expect(3);
_this.db.storeRule(_this.ruleId, JSON.stringify(_this.rule));
return _this.db.getRuleIds(function(err, obj) {
var _ref;
test.ok((_ref = _this.ruleId, __indexOf.call(obj, _ref) >= 0), 'Expected key not in rule key set');
return _this.db.getRule(_this.ruleId, function(err, obj) {
test.deepEqual(JSON.parse(obj), _this.rule, 'Retrieved rule is not what we expected');
return _this.db.getRules(function(err, obj) {
test.deepEqual(_this.rule, JSON.parse(obj[_this.ruleId]), 'Rule not in result set');
_this.db.deleteRule(_this.ruleId);
return test.done();
});
});
});
},
testUpdate: function(test) {
test.expect(1);
_this.db.storeRule(_this.ruleId, JSON.stringify(_this.rule));
_this.db.storeRule(_this.ruleId, JSON.stringify(_this.ruleNew));
return _this.db.getRule(_this.ruleId, function(err, obj) {
test.deepEqual(JSON.parse(obj), _this.ruleNew, 'Retrieved rule is not what we expected');
_this.db.deleteRule(_this.ruleId);
return test.done();
});
},
testDelete: function(test) {
test.expect(2);
_this.db.storeRule(_this.ruleId, JSON.stringify(_this.rule));
_this.db.deleteRule(_this.ruleId);
return _this.db.getRule(_this.ruleId, function(err, obj) {
test.strictEqual(obj, null, 'Rule still exists');
return _this.db.getRuleIds(function(err, obj) {
var _ref;
test.ok((_ref = _this.ruleId, __indexOf.call(obj, _ref) < 0), 'Rule key still exists in set');
return test.done();
});
});
},
testLink: function(test) {
test.expect(2);
_this.db.linkRule(_this.ruleId, _this.userId);
return _this.db.getRuleLinkedUsers(_this.ruleId, function(err, obj) {
var _ref;
test.ok((_ref = _this.userId, __indexOf.call(obj, _ref) >= 0), "Rule not linked to user " + _this.userId);
return _this.db.getUserLinkedRules(_this.userId, function(err, obj) {
var _ref1;
test.ok((_ref1 = _this.ruleId, __indexOf.call(obj, _ref1) >= 0), "User not linked to rule " + _this.ruleId);
return test.done();
});
});
},
testUnlink: function(test) {
test.expect(2);
_this.db.linkRule(_this.ruleId, _this.userId);
_this.db.unlinkRule(_this.ruleId, _this.userId);
return _this.db.getRuleLinkedUsers(_this.ruleId, function(err, obj) {
var _ref;
test.ok((_ref = _this.userId, __indexOf.call(obj, _ref) < 0), "Rule still linked to user " + _this.userId);
return _this.db.getUserLinkedRules(_this.userId, function(err, obj) {
var _ref1;
test.ok((_ref1 = _this.ruleId, __indexOf.call(obj, _ref1) < 0), "User still linked to rule " + _this.ruleId);
return test.done();
});
});
},
testActivate: function(test) {
var usr;
test.expect(3);
usr = {
username: "tester-1",
password: "tester-1"
};
_this.db.storeUser(usr);
_this.db.activateRule(_this.ruleId, _this.userId);
return _this.db.getRuleActivatedUsers(_this.ruleId, function(err, obj) {
var _ref;
test.ok((_ref = _this.userId, __indexOf.call(obj, _ref) >= 0), "Rule not activated for user " + _this.userId);
return _this.db.getUserActivatedRules(_this.userId, function(err, obj) {
var _ref1;
test.ok((_ref1 = _this.ruleId, __indexOf.call(obj, _ref1) >= 0), "User not activated for rule " + _this.ruleId);
return _this.db.getAllActivatedRuleIdsPerUser(function(err, obj) {
var _ref2;
test.ok(obj[_this.userId], "User not found in activated set");
test.ok((_ref2 = _this.ruleId, __indexOf.call(obj[_this.userId], _ref2) >= 0), "Rule " + _this.ruleId + " not in activated rules set");
return test.done();
});
});
});
},
testDeactivate: function(test) {
test.expect(3);
_this.db.activateRule(_this.ruleId, _this.userId);
_this.db.deactivateRule(_this.ruleId, _this.userId);
return _this.db.getRuleActivatedUsers(_this.ruleId, function(err, obj) {
var _ref;
test.ok((_ref = _this.userId, __indexOf.call(obj, _ref) < 0), "Rule still activated for user " + _this.userId);
return _this.db.getUserActivatedRules(_this.userId, function(err, obj) {
var _ref1;
test.ok((_ref1 = _this.ruleId, __indexOf.call(obj, _ref1) < 0), "User still activated for rule " + _this.ruleId);
return _this.db.getAllActivatedRuleIdsPerUser(function(err, obj) {
var _ref2;
test.ok((_ref2 = _this.ruleId, __indexOf.call(obj[_this.userId], _ref2) < 0), "Rule " + _this.ruleId + " still in activated rules set");
return test.done();
});
});
});
},
testUnlinkAndDeactivateAfterDeletion: function(test) {
var fWaitForDeletion, fWaitForTest;
test.expect(2);
_this.db.storeRule(_this.ruleId, JSON.stringify(_this.rule));
_this.db.linkRule(_this.ruleId, _this.userId);
_this.db.activateRule(_this.ruleId, _this.userId);
fWaitForTest = function() {
return _this.db.getUserLinkedRules(_this.userId, function(err, obj) {
var _ref;
test.ok((_ref = _this.ruleId, __indexOf.call(obj, _ref) < 0), "Rule " + _this.ruleId + " still linked to user " + _this.userId);
return _this.db.getUserActivatedRules(_this.userId, function(err, obj) {
var _ref1;
test.ok((_ref1 = _this.ruleId, __indexOf.call(obj, _ref1) < 0), "Rule " + _this.ruleId + " still activated for user " + _this.userId);
return test.done();
});
});
};
fWaitForDeletion = function() {
_this.db.deleteRule(_this.ruleId);
return setTimeout(fWaitForTest, 100);
};
return setTimeout(fWaitForDeletion, 100);
} }
}; };

View file

@ -22,7 +22,7 @@ exports.testParameters = ( test ) =>
exports.testDifferentConfigFile = ( test ) => exports.testDifferentConfigFile = ( test ) =>
test.expect 1 test.expect 1
@conf @conf
configPath: 'testing/jsonWrongConfig.json' configPath: path.join 'testing', 'files', 'jsonWrongConfig.json'
test.ok @conf.isReady(), 'Different path not loaded!' test.ok @conf.isReady(), 'Different path not loaded!'
test.done() test.done()

View file

@ -1,6 +1,5 @@
exports.setUp = ( cb ) => exports.setUp = ( cb ) =>
@log = require '../js-coffee/logging'
@db = require '../js-coffee/db_interface' @db = require '../js-coffee/db_interface'
@db logType: 2 @db logType: 2
cb() cb()
@ -8,17 +7,20 @@ exports.setUp = ( cb ) =>
exports.availability = exports.availability =
testRequire: ( test ) => testRequire: ( test ) =>
test.expect 1 test.expect 1
test.ok @db, 'DB interface loaded' test.ok @db, 'DB interface loaded'
test.done() test.done()
testConnect: ( test ) => testConnect: ( test ) =>
test.expect 1 test.expect 1
@db.isConnected ( err ) -> @db.isConnected ( err ) ->
test.ifError err, 'Connection failed!' test.ifError err, 'Connection failed!'
test.done() test.done()
testNoConfig: ( test ) => testNoConfig: ( test ) =>
test.expect 1 test.expect 1
@db @db
configPath: 'nonexistingconf.file' configPath: 'nonexistingconf.file'
@db.isConnected ( err ) -> @db.isConnected ( err ) ->
@ -27,16 +29,18 @@ exports.availability =
testWrongConfig: ( test ) => testWrongConfig: ( test ) =>
test.expect 1 test.expect 1
@db { configPath: 'testing/jsonWrongConfig.json' } @db { configPath: 'testing/jsonWrongConfig.json' }
@db.isConnected ( err ) -> @db.isConnected ( err ) ->
test.ok err, 'Still connected!?' test.ok err, 'Still connected!?'
test.done() test.done()
testPurgeQueue: ( test ) => testPurgeQueue: ( test ) =>
test.expect 2
evt = evt =
eventid: '1' eventid: '1'
event: 'mail' event: 'mail'
test.expect 2
@db.pushEvent evt @db.pushEvent evt
@db.purgeEventQueue() @db.purgeEventQueue()
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
@ -57,30 +61,41 @@ exports.events =
testEmptyPopping: ( test ) => testEmptyPopping: ( test ) =>
test.expect 2 test.expect 2
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
test.ifError err, 'Error during pop after purging!' test.ifError err,
test.strictEqual obj, null, 'There was an event in the queue!?' 'Error during pop after purging!'
test.strictEqual obj, null,
'There was an event in the queue!?'
test.done() test.done()
testEmptyPushing: ( test ) => testEmptyPushing: ( test ) =>
test.expect 2 test.expect 2
@db.pushEvent null @db.pushEvent null
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
test.ifError err, 'Error during non-empty pushing!' test.ifError err,
test.strictEqual obj, null, 'There was an event in the queue!?' 'Error during non-empty pushing!'
test.strictEqual obj, null,
'There was an event in the queue!?'
test.done() test.done()
testNonEmptyPopping: ( test ) => testNonEmptyPopping: ( test ) =>
test.expect 3 test.expect 3
@db.pushEvent @evt1 @db.pushEvent @evt1
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
test.ifError err, 'Error during non-empty popping!' test.ifError err,
test.notStrictEqual obj, null, 'There was no event in the queue!' 'Error during non-empty popping!'
test.deepEqual @evt1, obj, 'Wrong event in queue!' test.notStrictEqual obj, null,
'There was no event in the queue!'
test.deepEqual @evt1, obj,
'Wrong event in queue!'
test.done() test.done()
testMultiplePushAndPops: ( test ) => testMultiplePushAndPops: ( test ) =>
test.expect 6 test.expect 6
semaphore = 2 semaphore = 2
forkEnds = () -> forkEnds = () ->
test.done() if --semaphore is 0 test.done() if --semaphore is 0
@ -89,109 +104,548 @@ exports.events =
@db.pushEvent @evt2 @db.pushEvent @evt2
# eventually it would be wise to not care about the order of events # eventually it would be wise to not care about the order of events
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
test.ifError err, 'Error during multiple push and pop!' test.ifError err,
test.notStrictEqual obj, null, 'There was no event in the queue!' 'Error during multiple push and pop!'
test.deepEqual @evt1, obj, 'Wrong event in queue!' test.notStrictEqual obj, null,
'There was no event in the queue!'
test.deepEqual @evt1, obj,
'Wrong event in queue!'
forkEnds() forkEnds()
@db.popEvent ( err, obj ) => @db.popEvent ( err, obj ) =>
test.ifError err, 'Error during multiple push and pop!' test.ifError err,
test.notStrictEqual obj, null, 'There was no event in the queue!' 'Error during multiple push and pop!'
test.deepEqual @evt2, obj, 'Wrong event in queue!' test.notStrictEqual obj, null,
'There was no event in the queue!'
test.deepEqual @evt2, obj,
'Wrong event in queue!'
forkEnds() forkEnds()
exports.action_modules = exports.action_invoker =
# setUp: ( cb ) => testCreateAndRead: ( test ) =>
# @db logType: 1
# cb()
testModule: ( test ) =>
test.expect 4
action1name = 'test-action-module_1'
action1 = 'unit-test action module 1 content'
fCheckSetEntry = ( err , obj ) =>
test.ok action1name in obj, 'Expected key not in action-modules set'
@db.getActionModule action1name, fCheckModuleExists
fCheckModuleExists = ( err , obj ) =>
test.strictEqual obj, action1, 'Retrieved Action Module is not what we expected'
@log.print 'delete action module'
@db.deleteActionModule action1name
@log.print 'tried to delete action module'
@db.getActionModule action1name, fCheckModuleNotExists
fCheckModuleNotExists = ( err , obj ) =>
@log.print 'got action module'
test.strictEqual obj, null, 'Action module still exists'
@log.print 'compared action module'
@db.getActionModuleIds fCheckModuleNotExistsInSet
fCheckModuleNotExistsInSet = ( err , obj ) =>
test.ok action1name not in obj, 'Action module key still exists in set'
test.done()
@db.storeActionModule action1name, action1
@db.getActionModuleIds fCheckSetEntry
testFetchSeveralModules: ( test ) =>
semaphore = 2
test.expect 3 test.expect 3
action1name = 'test-action-module_1'
action2name = 'test-action-module_2'
action1 = 'unit-test action module 1 content'
action2 = 'unit-test action module 2 content'
fCheckModule = ( mod ) -> id = 'test-action-invoker'
action = 'unit-test action invoker content'
# store an entry to start with
@db.storeActionInvoker id, action
# test that the ID shows up in the set
@db.getActionInvokerIds ( err , obj ) =>
test.ok id in obj,
'Expected key not in action-invokers set'
# the retrieved object really is the one we expected
@db.getActionInvoker id, ( err , obj ) =>
test.strictEqual obj, action,
'Retrieved Action Invoker is not what we expected'
# Ensure the action invoker is in the list of all existing ones
@db.getActionInvokers ( err , obj ) =>
test.deepEqual action, obj[id],
'Action Invoker ist not in result set'
@db.deleteActionInvoker id
test.done()
testUpdate: ( test ) =>
test.expect 2
id = 'test-action-invoker'
action = 'unit-test action invoker content'
actionNew = 'unit-test action invoker new content'
# store an entry to start with
@db.storeActionInvoker id, action
@db.storeActionInvoker id, actionNew
# the retrieved object really is the one we expected
@db.getActionInvoker id, ( err , obj ) =>
test.strictEqual obj, actionNew,
'Retrieved Action Invoker is not what we expected'
# Ensure the action invoker is in the list of all existing ones
@db.getActionInvokers ( err , obj ) =>
test.deepEqual actionNew, obj[id],
'Action Invoker ist not in result set'
@db.deleteActionInvoker id
test.done()
testDelete: ( test ) =>
test.expect 2
id = 'test-action-invoker'
action = 'unit-test action invoker content'
# store an entry to start with
@db.storeActionInvoker id, action
# Ensure the action invoker has been deleted
@db.deleteActionInvoker id
@db.getActionInvoker id, ( err , obj ) =>
test.strictEqual obj, null,
'Action Invoker still exists'
# Ensure the ID has been removed from the set
@db.getActionInvokerIds ( err , obj ) =>
test.ok id not in obj,
'Action Invoker key still exists in set'
test.done()
testFetchSeveral: ( test ) =>
test.expect 3
semaphore = 2
action1name = 'test-action-invoker_1'
action2name = 'test-action-invoker_2'
action1 = 'unit-test action invoker 1 content'
action2 = 'unit-test action invoker 2 content'
fCheckInvoker = ( modname, mod ) =>
myTest = test myTest = test
sem = semaphore
forkEnds = () -> forkEnds = () ->
console.log 'fork ends' myTest.done() if --semaphore is 0
myTest.done() if --sem is 0 ( err, obj ) =>
console.log 'check module' myTest.strictEqual mod, obj,
( err, obj ) -> "Invoker #{ modname } does not equal the expected one"
console.log 'db answered' @db.deleteActionInvoker modname
myTest.strictEqual mod, obj, "Module does not equal the expected one"
forkEnds() forkEnds()
fCheckSetEntries = ( err, obj ) -> @db.storeActionInvoker action1name, action1
test.ok action1name in obj and action2name in obj, 'Not all action module Ids in set' @db.storeActionInvoker action2name, action2
console.log 'setentries fetched' @db.getActionInvokerIds ( err, obj ) =>
@db.getActionModule action1name, fCheckModule(action1) test.ok action1name in obj and action2name in obj,
@db.getActionModule action2name, fCheckModule(action2) 'Not all action invoker Ids in set'
@db.getActionInvoker action1name, fCheckInvoker action1name, action1
@db.storeActionModule action1name, action1 @db.getActionInvoker action2name, fCheckInvoker action2name, action2
@db.storeActionModule action2name, action2
@db.getActionModuleIds fCheckSetEntries
# testFetchModules: ( test ) => exports.action_invoker_params =
# test.expect 0 testCreateAndRead: ( test ) =>
# test.done() test.expect 2
# testStoreParams: ( test ) => userId = 'tester1'
# test.expect 0 actionId = 'test-action-invoker_1'
# test.done() params = 'shouldn\'t this be an object?'
# testFetchParams: ( test ) => # store an entry to start with
# test.expect 0 @db.storeActionParams actionId, userId, params
# test.done()
# test that the ID shows up in the set
@db.getActionParamsIds ( err, obj ) =>
test.ok actionId+':'+userId in obj,
'Expected key not in action-params set'
# the retrieved object really is the one we expected
@db.getActionParams actionId, userId, ( err, obj ) =>
test.strictEqual obj, params,
'Retrieved action params is not what we expected'
@db.deleteActionParams actionId, userId
test.done()
# exports.event_modules = testUpdate: ( test ) =>
# test: ( test ) => test.expect 1
# test.expect 0
# test.done() userId = 'tester1'
actionId = 'test-action-invoker_1'
params = 'shouldn\'t this be an object?'
paramsNew = 'shouldn\'t this be a new object?'
# store an entry to start with
@db.storeActionParams actionId, userId, params
@db.storeActionParams actionId, userId, paramsNew
# the retrieved object really is the one we expected
@db.getActionParams actionId, userId, ( err, obj ) =>
test.strictEqual obj, paramsNew,
'Retrieved action params is not what we expected'
@db.deleteActionParams actionId, userId
test.done()
testDelete: ( test ) =>
test.expect 2
userId = 'tester1'
actionId = 'test-action-invoker_1'
params = 'shouldn\'t this be an object?'
# store an entry to start with and delte it right away
@db.storeActionParams actionId, userId, params
@db.deleteActionParams actionId, userId
# Ensure the action params have been deleted
@db.getActionParams actionId, userId, ( err, obj ) =>
test.strictEqual obj, null,
'Action params still exists'
# Ensure the ID has been removed from the set
@db.getActionParamsIds ( err, obj ) =>
test.ok actionId+':'+userId not in obj,
'Action Params key still exists in set'
test.done()
# exports.rules = exports.event_poller =
# test: ( test ) => testCreateAndRead: ( test ) =>
# test.expect 0 test.expect 3
# test.done()
id = 'test-event-poller'
event = 'unit-test event poller content'
# store an entry to start with
@db.storeEventPoller id, event
# test that the ID shows up in the set
@db.getEventPollerIds ( err , obj ) =>
test.ok id in obj,
'Expected key not in event-pollers set'
# the retrieved object really is the one we expected
@db.getEventPoller id, ( err , obj ) =>
test.strictEqual obj, event,
'Retrieved Event Poller is not what we expected'
# Ensure the event poller is in the list of all existing ones
@db.getEventPollers ( err , obj ) =>
test.deepEqual event, obj[id],
'Event Poller ist not in result set'
@db.deleteEventPoller id
test.done()
testUpdate: ( test ) =>
test.expect 2
id = 'test-event-poller'
event = 'unit-test event poller content'
eventNew = 'unit-test event poller new content'
# store an entry to start with
@db.storeEventPoller id, event
@db.storeEventPoller id, eventNew
# the retrieved object really is the one we expected
@db.getEventPoller id, ( err , obj ) =>
test.strictEqual obj, eventNew,
'Retrieved Event Poller is not what we expected'
# Ensure the event poller is in the list of all existing ones
@db.getEventPollers ( err , obj ) =>
test.deepEqual eventNew, obj[id],
'Event Poller ist not in result set'
@db.deleteEventPoller id
test.done()
testDelete: ( test ) =>
test.expect 2
id = 'test-event-poller'
event = 'unit-test event poller content'
# store an entry to start with
@db.storeEventPoller id, event
# Ensure the event poller has been deleted
@db.deleteEventPoller id
@db.getEventPoller id, ( err , obj ) =>
test.strictEqual obj, null,
'Event Poller still exists'
# Ensure the ID has been removed from the set
@db.getEventPollerIds ( err , obj ) =>
test.ok id not in obj,
'Event Poller key still exists in set'
test.done()
testFetchSeveral: ( test ) =>
test.expect 3
semaphore = 2
event1name = 'test-event-poller_1'
event2name = 'test-event-poller_2'
event1 = 'unit-test event poller 1 content'
event2 = 'unit-test event poller 2 content'
fCheckPoller = ( modname, mod ) =>
myTest = test
forkEnds = () ->
myTest.done() if --semaphore is 0
( err, obj ) =>
myTest.strictEqual mod, obj,
"Invoker #{ modname } does not equal the expected one"
@db.deleteEventPoller modname
forkEnds()
@db.storeEventPoller event1name, event1
@db.storeEventPoller event2name, event2
@db.getEventPollerIds ( err, obj ) =>
test.ok event1name in obj and event2name in obj,
'Not all event poller Ids in set'
@db.getEventPoller event1name, fCheckPoller event1name, event1
@db.getEventPoller event2name, fCheckPoller event2name, event2
exports.event_poller_params =
testCreateAndRead: ( test ) =>
test.expect 2
userId = 'tester1'
eventId = 'test-event-poller_1'
params = 'shouldn\'t this be an object?'
# store an entry to start with
@db.storeEventParams eventId, userId, params
# test that the ID shows up in the set
@db.getEventParamsIds ( err, obj ) =>
test.ok eventId+':'+userId in obj,
'Expected key not in event-params set'
# the retrieved object really is the one we expected
@db.getEventParams eventId, userId, ( err, obj ) =>
test.strictEqual obj, params,
'Retrieved event params is not what we expected'
@db.deleteEventParams eventId, userId
test.done()
testUpdate: ( test ) =>
test.expect 1
userId = 'tester1'
eventId = 'test-event-poller_1'
params = 'shouldn\'t this be an object?'
paramsNew = 'shouldn\'t this be a new object?'
# store an entry to start with
@db.storeEventParams eventId, userId, params
@db.storeEventParams eventId, userId, paramsNew
# the retrieved object really is the one we expected
@db.getEventParams eventId, userId, ( err, obj ) =>
test.strictEqual obj, paramsNew,
'Retrieved event params is not what we expected'
@db.deleteEventParams eventId, userId
test.done()
testDelete: ( test ) =>
test.expect 2
userId = 'tester1'
eventId = 'test-event-poller_1'
params = 'shouldn\'t this be an object?'
# store an entry to start with and delete it right away
@db.storeEventParams eventId, userId, params
@db.deleteEventParams eventId, userId
# Ensure the event params have been deleted
@db.getEventParams eventId, userId, ( err, obj ) =>
test.strictEqual obj, null,
'Event params still exists'
# Ensure the ID has been removed from the set
@db.getEventParamsIds ( err, obj ) =>
test.ok eventId+':'+userId not in obj,
'Event Params key still exists in set'
test.done()
exports.rules =
setUp: ( cb ) =>
@db logType: 1
@userId = 'tester-1'
@ruleId = 'test-rule_1'
@rule =
"id": "rule_id",
"event": "custom",
"condition":
"property": "yourValue",
"actions": []
@ruleNew =
"id": "rule_new",
"event": "custom",
"condition":
"property": "yourValue",
"actions": []
cb()
tearDown: ( cb ) =>
@db.deleteRule @ruleId
cb()
testCreateAndRead: ( test ) =>
test.expect 3
# store an entry to start with
@db.storeRule @ruleId, JSON.stringify(@rule)
# test that the ID shows up in the set
@db.getRuleIds ( err, obj ) =>
test.ok @ruleId in obj,
'Expected key not in rule key set'
# the retrieved object really is the one we expected
@db.getRule @ruleId, ( err, obj ) =>
test.deepEqual JSON.parse(obj), @rule,
'Retrieved rule is not what we expected'
# Ensure the rule is in the list of all existing ones
@db.getRules ( err , obj ) =>
test.deepEqual @rule, JSON.parse(obj[@ruleId]),
'Rule not in result set'
@db.deleteRule @ruleId
test.done()
testUpdate: ( test ) =>
test.expect 1
# store an entry to start with
@db.storeRule @ruleId, JSON.stringify(@rule)
@db.storeRule @ruleId, JSON.stringify(@ruleNew)
# the retrieved object really is the one we expected
@db.getRule @ruleId, ( err, obj ) =>
test.deepEqual JSON.parse(obj), @ruleNew,
'Retrieved rule is not what we expected'
@db.deleteRule @ruleId
test.done()
testDelete: ( test ) =>
test.expect 2
# store an entry to start with and delete it right away
@db.storeRule @ruleId, JSON.stringify(@rule)
@db.deleteRule @ruleId
# Ensure the event params have been deleted
@db.getRule @ruleId, ( err, obj ) =>
test.strictEqual obj, null,
'Rule still exists'
# Ensure the ID has been removed from the set
@db.getRuleIds ( err, obj ) =>
test.ok @ruleId not in obj,
'Rule key still exists in set'
test.done()
testLink: ( test ) =>
test.expect 2
# link a rule to the user
@db.linkRule @ruleId, @userId
# Ensure the user is linked to the rule
@db.getRuleLinkedUsers @ruleId, ( err, obj ) =>
test.ok @userId in obj,
"Rule not linked to user #{ @userId }"
# Ensure the rule is linked to the user
@db.getUserLinkedRules @userId, ( err, obj ) =>
test.ok @ruleId in obj,
"User not linked to rule #{ @ruleId }"
test.done()
testUnlink: ( test ) =>
test.expect 2
# link and unlink immediately afterwards
@db.linkRule @ruleId, @userId
@db.unlinkRule @ruleId, @userId
# Ensure the user is linked to the rule
@db.getRuleLinkedUsers @ruleId, ( err, obj ) =>
test.ok @userId not in obj,
"Rule still linked to user #{ @userId }"
# Ensure the rule is linked to the user
@db.getUserLinkedRules @userId, ( err, obj ) =>
test.ok @ruleId not in obj,
"User still linked to rule #{ @ruleId }"
test.done()
testActivate: ( test ) =>
test.expect 3
usr =
username: "tester-1"
password: "tester-1"
@db.storeUser usr
@db.activateRule @ruleId, @userId
# activate a rule for a user
# Ensure the user is activated to the rule
@db.getRuleActivatedUsers @ruleId, ( err, obj ) =>
test.ok @userId in obj,
"Rule not activated for user #{ @userId }"
# Ensure the rule is linked to the user
@db.getUserActivatedRules @userId, ( err, obj ) =>
test.ok @ruleId in obj,
"User not activated for rule #{ @ruleId }"
# Ensure the rule is showing up in all active rules
@db.getAllActivatedRuleIdsPerUser ( err, obj ) =>
test.ok obj[@userId],
"User not found in activated set"
test.ok @ruleId in obj[@userId],
"Rule #{ @ruleId } not in activated rules set"
test.done()
testDeactivate: ( test ) =>
test.expect 3
# store an entry to start with and link it to te user
@db.activateRule @ruleId, @userId
@db.deactivateRule @ruleId, @userId
# Ensure the user is linked to the rule
@db.getRuleActivatedUsers @ruleId, ( err, obj ) =>
test.ok @userId not in obj,
"Rule still activated for user #{ @userId }"
# Ensure the rule is linked to the user
@db.getUserActivatedRules @userId, ( err, obj ) =>
test.ok @ruleId not in obj,
"User still activated for rule #{ @ruleId }"
# Ensure the rule is showing up in all active rules
@db.getAllActivatedRuleIdsPerUser ( err, obj ) =>
test.ok @ruleId not in obj[@userId],
"Rule #{ @ruleId } still in activated rules set"
test.done()
testUnlinkAndDeactivateAfterDeletion: ( test ) =>
test.expect 2
# store an entry to start with and link it to te user
@db.storeRule @ruleId, JSON.stringify(@rule)
@db.linkRule @ruleId, @userId
@db.activateRule @ruleId, @userId
# We need to wait here and there since these calls are asynchronous
fWaitForTest = () =>
# Ensure the user is unlinked to the rule
@db.getUserLinkedRules @userId, ( err, obj ) =>
test.ok @ruleId not in obj,
"Rule #{ @ruleId } still linked to user #{ @userId }"
# Ensure the rule is deactivated for the user
@db.getUserActivatedRules @userId, ( err, obj ) =>
test.ok @ruleId not in obj,
"Rule #{ @ruleId } still activated for user #{ @userId }"
test.done()
fWaitForDeletion = () =>
@db.deleteRule @ruleId
setTimeout fWaitForTest, 100
setTimeout fWaitForDeletion, 100
# exports.users = # exports.users =
# test: ( test ) => # test: ( test ) =>
# test.expect 0 # test.expect 0
# test.done() # test.done()
# TODO on delete, remove all rules for the user if he's deleted
exports.tearDown = ( cb ) => exports.tearDown = ( cb ) =>

View file

@ -12,5 +12,6 @@
{{message}} {{message}}
</p> </p>
</div> </div>
<div id="info"></div>
</body> </body>
</html> </html>

View file

@ -12,5 +12,6 @@
Error: {{message}} Error: {{message}}
</p> </p>
</div> </div>
<div id="info"></div>
</body> </body>
</html> </html>

View file

@ -73,6 +73,7 @@ exports.myOwnEventFunction = function( callback ) {
<button id="but_submit">save</button> <button id="but_submit">save</button>
</p> </p>
</div> </div>
<div id="info"></div>
<script type="text/javascript"> <script type="text/javascript">
$('#select_type').change(function(e) { $('#select_type').change(function(e) {

View file

@ -47,6 +47,7 @@
</form> </form>
</p> </p>
</div> </div>
<div id="info"></div>
<script type="text/javascript"> <script type="text/javascript">
$( "#form_rule" ).submit(function( event ) { $( "#form_rule" ).submit(function( event ) {

View file

@ -4,17 +4,17 @@
<div id="menubar_event">invoke events</div> <div id="menubar_event">invoke events</div>
<div id="menubar_logout">logout</div> <div id="menubar_logout">logout</div>
<script> <script>
$('#menubar_modules').click(function() { $( '#menubar_modules' ).click( function() {
window.location.href = 'forge_modules'; window.location.href = 'forge_modules';
}); });
$('#menubar_rules').click(function() { $( '#menubar_rules' ).click( function() {
window.location.href = 'forge_rules'; window.location.href = 'forge_rules';
}); });
$('#menubar_event').click(function() { $( '#menubar_event' ).click( function() {
window.location.href = 'invoke_event'; window.location.href = 'invoke_event';
}); });
$('#menubar_logout').click(function() { $( '#menubar_logout' ).click( function() {
$.post('/logout').done(function() { $.post( '/logout' ).done( function() {
window.location.href = document.URL; window.location.href = document.URL;
}); });
}); });

View file

@ -0,0 +1,11 @@
<link rel="stylesheet" type="text/css" href="style.css">
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
<script type='text/javascript'>
var checkIncludes = function () {
if( window.$ === undefined ) {
document.getElementById('info').innerHTML = 'Not all required libraries have been loaded. Are you connected to the internet?';
}
};
window.addEventListener( "load" , checkIncludes, true );
</script>

View file

@ -2,9 +2,11 @@
<html> <html>
<head> <head>
<title>Login</title> <title>Login</title>
<link rel="stylesheet" type="text/css" href="style.css"> {{{head_requires}}}
<!-- <link rel="stylesheet" type="text/css" href="style.css">
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script> <script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha3.js"></script> <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha3.js"></script>
-->
</head> </head>
<body> <body>
<div id="mainbody"> <div id="mainbody">
@ -15,9 +17,10 @@
</table> </table>
<button id="but_submit">login</button> <button id="but_submit">login</button>
</div> </div>
<div id="info"></div>
<script> <script>
$('#but_submit').click(function() { $('#but_submit').click(function() {
var hashedPassword = (CryptoJS.SHA3($('#password').val(), { outputLength: 512 })).toString(); var hashedPassword = (CryptoJS.SHA3($('#password').val(), { outputLength: 512 })).toString();
$.post('/login', { username: $('#username').val(), password: hashedPassword }) $.post('/login', { username: $('#username').val(), password: hashedPassword })
.done(function(data) { .done(function(data) {
window.location.href = document.URL; window.location.href = document.URL;

View file

@ -1,3 +0,0 @@
<link rel="stylesheet" type="text/css" href="style.css">
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>

View file

@ -23,6 +23,7 @@
<button id="but_submit">invoke</button> <button id="but_submit">invoke</button>
</p> </p>
</div> </div>
<div id="info"></div>
<script> <script>
$('#but_submit').click(function() { $('#but_submit').click(function() {

View file

@ -13,5 +13,6 @@
You only have these privileges: {{user.roles}} You only have these privileges: {{user.roles}}
</p> </p>
</div> </div>
<div id="info"></div>
</body> </body>
</html> </html>

View file

@ -13,5 +13,6 @@
Your roles are: {{user.roles}} Your roles are: {{user.roles}}
</p> </p>
</div> </div>
<div id="info"></div>
</body> </body>
</html> </html>

View file

@ -29,6 +29,14 @@ textarea {
cursor: pointer; cursor: pointer;
} }
#info {
padding-left: 10px;
padding-top: 30px;
font-family: Tahoma, sans-serif;
font-size: 0.75em;
color: #F33;
}
#menubar div:hover { #menubar div:hover {
background-color: #AAA; background-color: #AAA;
} }