pimatic
Version:
A home automation server and framework for the Raspberry PI running on node.js
145 lines (123 loc) • 4.7 kB
text/coffeescript
__ = require("i18n-pimatic").__
Promise = require 'bluebird'
assert = require 'cassert'
_ = require 'lodash'
S = require 'string'
crypto = require 'crypto'
module.exports = (env) ->
class UserManager
_allowPublicAccessCallbacks: []
constructor: (, , ) -> #nop
addUser: (username, user) ->
if _.findIndex(, {username: username}) isnt -1
throw new Error('A user with this username already exists')
unless user.username?
throw new Error('No username given')
unless user.role?
throw new Error('No role given')
.push( user = {
username: username
password: user.password
role: user.role
})
.saveConfig()
._emitUserAdded(user)
return page
updateUser: (username, user) ->
assert typeof username is "string"
assert typeof page is "object"
assert(if user.username? then typeof user.username is "string" else true)
assert(if user.password? then typeof user.password is "string" else true)
assert(if user.role? then typeof user.role is "string" else true)
theuser =
unless theuser?
throw new Error('User not found')
theuser.username = page.username if page.username?
theuser.password = page.password if page.password?
theuser.role = page.role if page.role?
.saveConfig()
._emitUserChanged(theuser)
return theuser
getUserByUsername: (username) -> _.find(, {username: username})
hasPermission: (username, scope, access) ->
assert scope in [
"pages", "rules", "variables", "messages", "config"
"events", "devices", "groups", "plugins", "updates",
"database"
]
assert access in ["read", "write", "none"]
user =
unless user?
throw new Error('User not found')
assert typeof user.role is "string"
role =
unless role?
throw new Error("No role with name #{user.role} found.")
permission = role.permissions[scope]
unless permission?
throw new Error("No permissions for #{scope} of #{user.role} found.")
switch access
when "read"
return (permission is "read" or permission is "write")
when "write"
return (permission is "write")
when "none"
return yes
else
return no
hasPermissionBoolean: (username, scope) ->
user =
unless user?
throw new Error('User not found')
assert typeof user.role is "string"
role =
unless role?
throw new Error("No role with name #{user.role} found.")
permission = role.permissions[scope]
unless permission?
throw new Error("No permissions for #{scope} of #{user.role} found.")
return (permission is true)
checkLogin: (username, password) ->
assert typeof username is "string"
assert typeof password is "string"
if username.length is 0 then return false
user =
unless user?
return false
return password is user.password
getRoleByName: (name) ->
assert typeof name is "string"
role = _.find(, {name: name})
return role
getPermissionsByUsername: (username) ->
user =
unless user?
throw new Error('User not found')
role =
unless role?
throw new Error("No role with name #{user.role} found.")
return role.permissions
getLoginTokenForUsername: (secret, username) ->
assert typeof username is "string"
assert username.length > 0
assert typeof secret is "string"
assert secret.length >= 32
user =
unless user?
throw new Error('User not found')
assert typeof user.password is "string"
assert user.password.length > 0
shasum = crypto.createHash('sha256')
shasum.update(secret, 'utf8')
shasum.update(user.password, 'utf8')
loginToken = shasum.digest('hex')
return loginToken
checkLoginToken: (secret, username, loginToken) ->
return loginToken is
isPublicAccessAllowed: (req) ->
for allow in
if allow(req) then return yes
return no
addAllowPublicAccessCallback: (callback) ->
.push callback
return exports = { UserManager }