summaryrefslogtreecommitdiffstats
path: root/did-model.lua
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2010-07-01 12:42:51 +0000
committerTed Trask <ttrask01@yahoo.com>2010-07-01 12:42:51 +0000
commit2536d0c904364e560b5fc2c4ab0460739426b274 (patch)
tree8f217baf5dcb484711d2cac04d2746ca351a0e86 /did-model.lua
parent072e06ced2652119c9c1d6fcd2fddeba8cd6445c (diff)
downloadacf-did-2536d0c904364e560b5fc2c4ab0460739426b274.tar.bz2
acf-did-2536d0c904364e560b5fc2c4ab0460739426b274.tar.xz
Added user/roles permissions on a DID-by-DID basis.
Diffstat (limited to 'did-model.lua')
-rw-r--r--did-model.lua287
1 files changed, 235 insertions, 52 deletions
diff --git a/did-model.lua b/did-model.lua
index d7b3a8d..0e2fb81 100644
--- a/did-model.lua
+++ b/did-model.lua
@@ -5,6 +5,8 @@ require("modelfunctions")
require("format")
require("validator")
require("luasql.postgres")
+require("authenticator")
+require("roles")
-- NOTE -- This is the SQL statement that should be run by the VoIP server to figure out the current extension for a DID
-- "SELECT extension FROM pubdid WHERE did='$1' AND 'now'>=starttime AND 'now'<endtime ORDER BY stale LIMIT 1"
@@ -22,6 +24,8 @@ local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
local env
local con
+local didlist
+
local database_creation_script = {
"CREATE AGGREGATE array_accum(anyelement) (SFUNC = array_append, STYPE = anyarray, INITCOND = '{}')",
"CREATE TABLE dbhistlog (logdatetime timestamp(3) without time zone NOT NULL, msgtext text, userid text)",
@@ -183,7 +187,7 @@ local groomdbhistlog = function()
logme("removed " .. res .. " old dbhistlog lines")
end
-local generatewhereclause = function(did, extension, identification, description, department, clause)
+local generatewhereclause = function(did, extension, identification, description, department, allowedlist, clause)
local sql = ""
local where = {}
-- We're going to use regular expressions so can search for substrings
@@ -203,6 +207,10 @@ local generatewhereclause = function(did, extension, identification, description
if department and department ~= "" then
where[#where+1] = "department ~* '"..escaperegex(department).."'"
end
+ --if allowedlist and #allowedlist > 0 then
+ if allowedlist then
+ where[#where+1] = "definition.did IN ('"..table.concat(allowedlist, "', '").."')"
+ end
if #where > 0 then
sql = " " .. (clause or "WHERE") .. " " .. table.concat(where, " AND ")
end
@@ -230,14 +238,14 @@ local getdefinitionentries = function(sql)
return entries
end
-local listunuseddefinitions = function(did, identification, description, department, page)
- local where = generatewhereclause(did, nil, identification, description, department, "AND")
+local listunuseddefinitions = function(did, identification, description, department, allowedlist, page)
+ local where = generatewhereclause(did, nil, identification, description, department, allowedlist, "AND")
local sql = "SELECT * FROM definition WHERE did NOT IN (SELECT did FROM rule)"..where.." ORDER BY did"..generatelimitclause(page)
return getdefinitionentries(sql)
end
-local countunuseddefinitions = function(did, identification, description, department)
- local where = generatewhereclause(did, nil, identification, description, department, "AND")
+local countunuseddefinitions = function(did, identification, description, department, allowedlist)
+ local where = generatewhereclause(did, nil, identification, description, department, allowedlist, "AND")
local sql = "SELECT count(*) FROM definition WHERE did NOT IN (SELECT did FROM rule)"..where
cur = assert (con:execute(sql))
local count = cur:fetch()
@@ -246,8 +254,8 @@ local countunuseddefinitions = function(did, identification, description, depart
end
-- Lists only the definitions that have rules, this also allows us to select based upon extension
-local listuseddefinitions = function(did, extension, identification, description, department, page)
- local where = string.gsub(generatewhereclause(did, extension, identification, description, department, "HAVING"), "extension", "array_to_string(array_accum(rule.extension), ', ')")
+local listuseddefinitions = function(did, extension, identification, description, department, allowedlist, page)
+ local where = string.gsub(generatewhereclause(did, extension, identification, description, department, allowedlist, "HAVING"), "extension", "array_to_string(array_accum(rule.extension), ', ')")
-- Combine with rules to get extensions, this will drop all dids that don't have rules
-- Relies on this custom aggregate function being defined
-- local sql = "CREATE AGGREGATE array_accum(anyelement)(sfunc = array_append, stype = anyarray, initcond = '{}')"
@@ -257,8 +265,8 @@ local listuseddefinitions = function(did, extension, identification, description
end
-- Counts only the definitions that have rules, this also allows us to select based upon extension
-local countuseddefinitions = function(did, extension, identification, description, department)
- local where = string.gsub(generatewhereclause(did, extension, identification, description, department, "HAVING"), "extension", "array_to_string(array_accum(rule.extension), ', ')")
+local countuseddefinitions = function(did, extension, identification, description, department, allowedlist)
+ local where = string.gsub(generatewhereclause(did, extension, identification, description, department, allowedlist, "HAVING"), "extension", "array_to_string(array_accum(rule.extension), ', ')")
-- Combine with rules to get extensions, this will drop all dids that don't have rules
-- Relies on this custom aggregate function being defined
-- local sql = "CREATE AGGREGATE array_accum(anyelement)(sfunc = array_append, stype = anyarray, initcond = '{}')"
@@ -271,8 +279,8 @@ local countuseddefinitions = function(did, extension, identification, descriptio
return count
end
-local listdefinitionsandextensions = function(did, identification, description, department, page)
- local where = generatewhereclause(did, nil, identification, description, department, "HAVING")
+local listdefinitionsandextensions = function(did, identification, description, department, allowedlist, page)
+ local where = generatewhereclause(did, nil, identification, description, department, allowedlist, "HAVING")
-- Combine with rules to get extensions, use LEFT JOIN to not drop all dids that don't have rules
-- Relies on this custom aggregate function being defined
-- local sql = "CREATE AGGREGATE array_accum(anyelement)(sfunc = array_append, stype = anyarray, initcond = '{}')"
@@ -281,21 +289,21 @@ local listdefinitionsandextensions = function(did, identification, description,
return getdefinitionentries(sql)
end
-local listdefinitions = function(did, identification, description, department, page)
- local sql = "SELECT * FROM definition"..generatewhereclause(did, nil, identification, description, department).." ORDER BY did"..generatelimitclause(page)
+local listdefinitions = function(did, identification, description, department, allowedlist, page)
+ local sql = "SELECT * FROM definition"..generatewhereclause(did, nil, identification, description, department, allowedlist).." ORDER BY did"..generatelimitclause(page)
return getdefinitionentries(sql)
end
-local countdefinitions = function(did, identification, description, department)
- local sql = "SELECT count(*) FROM definition"..generatewhereclause(did, nil, identification, description, department)
+local countdefinitions = function(did, identification, description, department, allowedlist)
+ local sql = "SELECT count(*) FROM definition"..generatewhereclause(did, nil, identification, description, department, allowedlist)
cur = assert (con:execute(sql))
local count = cur:fetch()
cur:close()
return count
end
-local listdefs = function(did, identification, description, department)
- local sql = "SELECT did FROM definition"..generatewhereclause(did, nil, identification, description, department).." ORDER BY did"
+local listdefs = function(did, identification, description, department, allowedlist)
+ local sql = "SELECT did FROM definition"..generatewhereclause(did, nil, identification, description, department, allowedlist).." ORDER BY did"
local entries = {}
cur = assert (con:execute(sql))
row = cur:fetch ({}, "a")
@@ -759,17 +767,56 @@ local determinepagedata = function(count, page)
return page_data
end
+local function parseentry(entry)
+ local allowedlist = {}
+ local restricted = (string.find(entry, "^true:") ~= nil)
+ for x in string.gmatch(string.match(entry, "[^:]*$") or "", "([^,]+),?") do
+ allowedlist[#allowedlist + 1] = x
+ end
+ return restricted, allowedlist
+end
+
+local function getallowedlist(self, userid)
+ local entry = authenticator.auth.read_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, userid) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+
+ -- also check to see if there are allowed files for this user's roles
+ local rols = authenticator.get_userinfo_roles(self, userid)
+ -- add in the guest role
+ rols.value[#rols.value + 1] = roles.guest_role
+ for i,role in ipairs(rols.value) do
+ local entry = authenticator.auth.read_entry(self, authenticator.roletable, self.conf.prefix..self.conf.controller, role) or ""
+ local restricted2, allowed2
+ restricted2, allowed2 = parseentry(entry)
+ restricted = restricted or restricted2
+ for i,x in ipairs(allowed2) do allowedlist[#allowedlist + 1] = x end
+ end
+ if not restricted then return nil end
+ return allowedlist
+end
+
+local function adduserpermission(self, userid, did)
+ local entry = authenticator.auth.read_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, userid) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+ allowedlist[#allowedlist+1] = did
+
+ authenticator.auth.write_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, userid, tostring(restricted)..":"..(table.concat(allowedlist, ",") or ""))
+end
+
-- ################################################################################
-- PUBLIC FUNCTIONS
-function getuseddefinitionlist(did, extension, identification, description, department, page)
+function getuseddefinitionlist(self, userid, did, extension, identification, description, department, page)
local def = createdefinitionlist(stripdash(did), extension, identification, description, department)
def.label = "Used "..def.label
+ local allowedlist = getallowedlist(self, userid)
local res, err = pcall(function()
local connected = databaseconnect(DatabaseUser)
- local count = countuseddefinitions(stripdash(did), extension, identification, description, department)
+ local count = countuseddefinitions(stripdash(did), extension, identification, description, department, allowedlist)
def.value.pagedata.value = determinepagedata(count, page)
- def.value.definitions.value = listuseddefinitions(stripdash(did), extension, identification, description, department, def.value.pagedata.value.page)
+ def.value.definitions.value = listuseddefinitions(stripdash(did), extension, identification, description, department, allowedlist, def.value.pagedata.value.page)
if connected then databasedisconnect() end
end)
if not res then
@@ -781,15 +828,16 @@ function getuseddefinitionlist(did, extension, identification, description, depa
return def
end
-function getunuseddefinitionlist(did, identification, description, department, page)
+function getunuseddefinitionlist(self, userid, did, identification, description, department, page)
local def = createdefinitionlist(stripdash(did), nil, identification, description, department)
def.value.extension = nil
def.label = "Unused "..def.label
+ local allowedlist = getallowedlist(self, userid)
local res, err = pcall(function()
local connected = databaseconnect(DatabaseUser)
- local count = countunuseddefinitions(stripdash(did), identification, description, department)
+ local count = countunuseddefinitions(stripdash(did), identification, description, department, allowedlist)
def.value.pagedata.value = determinepagedata(count, page)
- def.value.definitions.value = listunuseddefinitions(stripdash(did), identification, description, department, def.value.pagedata.value.page)
+ def.value.definitions.value = listunuseddefinitions(stripdash(did), identification, description, department, allowedlist, def.value.pagedata.value.page)
if connected then databasedisconnect() end
end)
if not res then
@@ -801,19 +849,20 @@ function getunuseddefinitionlist(did, identification, description, department, p
return def
end
-function getdefinitionlist(did, extension, identification, description, department, page)
+function getdefinitionlist(self, userid, did, extension, identification, description, department, page)
local def = createdefinitionlist(stripdash(did), extension, identification, description, department)
--def.value.extension = nil
+ local allowedlist = getallowedlist(self, userid)
local res, err = pcall(function()
local connected = databaseconnect(DatabaseUser)
if def.value.extension.value == "" then
- local count = countdefinitions(stripdash(did), identification, description, department)
+ local count = countdefinitions(stripdash(did), identification, description, department, allowedlist)
def.value.pagedata.value = determinepagedata(count, page)
- def.value.definitions.value = listdefinitionsandextensions(stripdash(did), identification, description, department, def.value.pagedata.value.page)
+ def.value.definitions.value = listdefinitionsandextensions(stripdash(did), identification, description, department, allowedlist, def.value.pagedata.value.page)
else
- local count = countuseddefinitions(stripdash(did), extension, identification, description, department)
+ local count = countuseddefinitions(stripdash(did), extension, identification, description, department, allowedlist)
def.value.pagedata.value = determinepagedata(count, page)
- def.value.definitions.value = listuseddefinitions(stripdash(did), extension, identification, description, department, def.value.pagedata.value.page)
+ def.value.definitions.value = listuseddefinitions(stripdash(did), extension, identification, description, department, allowedlist, def.value.pagedata.value.page)
end
if connected then databasedisconnect() end
end)
@@ -826,11 +875,12 @@ function getdefinitionlist(did, extension, identification, description, departme
return def
end
-function searchdefinitions(did)
+function searchdefinitions(self, userid, did)
+ local allowedlist = getallowedlist(self, userid)
local result = {}
local res, err = pcall(function()
local connected = databaseconnect(DatabaseUser)
- result = listdefs(did)
+ result = listdefs(did, nil, nil, nil, allowedlist)
if connected then databasedisconnect() end
end)
if not res then
@@ -839,7 +889,8 @@ function searchdefinitions(did)
return cfe({ type="list", value=result, label="DID list" })
end
-function getdefinition(did)
+function getdefinition(self, userid, did)
+ local allowedlist = getallowedlist(self, userid)
local errtxt
local group = {}
group.did = cfe({ value=stripdash(did) or "", label="DID" })
@@ -852,7 +903,7 @@ function getdefinition(did)
group.did.errtxt = "DID does not exist"
local res, err = pcall(function()
local connected = databaseconnect(DatabaseUser)
- local definition = listdefinitions(stripdash(did))
+ local definition = listdefinitions(stripdash(did), nil, nil, nil, allowedlist)
local rules = listrules(stripdash(did))
if connected then databasedisconnect() end
if #definition == 1 then
@@ -877,7 +928,8 @@ function getdefinition(did)
end
-- If exists true, then make sure exists first, if false or undefined, make sure doesn't exist
-function savedefinition(defin, test, exists)
+function savedefinition(self, userid, defin, test, exists)
+ local allowedlist = getallowedlist(self, userid)
-- remove blank entries, if present
defin.value.rules.value = string.gsub("\n"..format.dostounix(defin.value.rules.value), "\n%s*,%s*,%s*,%s*,%s*,%s*0000000", "")
defin.value.rules.value = string.gsub(defin.value.rules.value, "$\n", "")
@@ -909,7 +961,7 @@ function savedefinition(defin, test, exists)
else
connected = databaseconnect(DatabaseUser)
end
- local def = listdefinitions(definition.did)
+ local def = listdefinitions(definition.did, nil, nil, nil, allowedlist)
if #def > 0 and not exists then
defin.value.did.errtxt = "DID Number already exists"
elseif #def == 0 and exists then
@@ -955,18 +1007,19 @@ function savedefinition(defin, test, exists)
return defin
end
-function updatedefinition(defin, test)
- return savedefinition(defin, test, true)
+function updatedefinition(self, userid, defin, test)
+ return savedefinition(self, userid, defin, test, true)
end
-function deletedefinition(did)
+function deletedefinition(self, userid, did)
+ local allowedlist = getallowedlist(self, userid)
local result = cfe({ label="Delete DID Number Result", errtxt="DID Number does not exist" })
did = stripdash(did)
local res, err = pcall(function()
databasedisconnect()
local pw = format.parse_ini_file(fs.read_file(configfile) or "", "", "password") or ""
databaseconnect(DatabaseOwner, pw)
- local def = listdefs(did)
+ local def = listdefs(did, nil, nil, nil, allowedlist)
if #def == 1 then
deletedefinitionentry(did)
result.value = "DID Number Deleted"
@@ -1035,16 +1088,13 @@ function publishdefinition(did)
local res, err = pcall(function()
databasedisconnect()
databaseconnect(DatabaseOwner, pw)
- local dids = listdefs()
- for i,d in ipairs(dids) do
- if d == did then
- local rules = getdailyentry(did)
- publishrules(did, rules)
- errtxt = nil
- result = "Published DID rules"
- --logme("Published DID "..did)
- break
- end
+ local def = listdefs(did)
+ if #def == 1 then
+ local rules = getdailyentry(did)
+ publishrules(did, rules)
+ errtxt = nil
+ result = "Published DID rules"
+ --logme("Published DID "..did)
end
databasedisconnect()
end)
@@ -1061,14 +1111,14 @@ function publishalldefinitions()
local res, err = pcall(function()
databasedisconnect()
databaseconnect(DatabaseOwner, pw)
- local dids = listdefs()
+ didlist = didlist or listdefs()
local time = os.time()
- for i,did in ipairs(dids) do
+ for i,did in ipairs(didlist) do
local rules = getdailyentry(did, time)
publishrules(did, rules)
end
- result = "Published "..#dids.." DID rules"
- logme("Publishing "..#dids.." DIDs took "..os.time()-time.." seconds")
+ result = "Published "..#didlist.." DID rules"
+ logme("Publishing "..#didlist.." DIDs took "..os.time()-time.." seconds")
groomdbhistlog()
databasedisconnect()
end)
@@ -1171,3 +1221,136 @@ function getactivitylog()
return retval
end
+
+function getpermissionslist(self)
+ local users = authenticator.list_users(self)
+ local userlist = {}
+ for i,user in ipairs(users) do
+ local entry = authenticator.auth.read_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, user) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+ userlist[#userlist + 1] = {id=user, restricted=restricted, allowed=allowedlist}
+ end
+ -- Need to check for roles as well as users
+ local rolelist = {}
+ local rols = roles.list_all_roles(self)
+ for i,role in ipairs(rols) do
+ local entry = authenticator.auth.read_entry(self, authenticator.roletable, self.conf.prefix..self.conf.controller, role) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+ rolelist[#rolelist + 1] = {id=role, restricted=restricted, allowed=allowedlist}
+ end
+ table.sort(userlist, function(a,b) return a.id < b.id end)
+ return cfe({ type="structure", value={user=userlist, role=rolelist}, label="DID Permissions" })
+end
+
+local function validatepermissions(permissions)
+ local success = true
+ if not didlist then
+ local res, err = pcall(function()
+ local connected = databaseconnect(DatabaseUser)
+ didlist = listdefs()
+ if connected then databasedisconnect() end
+ end)
+ if not res then
+ permissions.value.allowed.errtxt = err
+ success = false
+ end
+ end
+ if success then
+ local newlist = {}
+ if not reversedidlist then
+ reversedidlist = {}
+ for i,d in ipairs(didlist) do
+ reversedidlist[d] = i
+ end
+ end
+ for i,d in ipairs(permissions.value.allowed.value) do
+ local nd = stripdash(d)
+ newlist[#newlist+1] = nd
+ if not reversedidlist[nd] then
+ success = false
+ permissions.value.allowed.errtxt = "Contains invalid DID"
+ break
+ end
+ end
+ permissions.value.allowed.value = newlist
+ end
+ return success
+end
+
+local function validateuserpermissions(self, userpermissions)
+ local success = false
+ userpermissions.value.userid.errtxt = "Invalid user"
+ local users = authenticator.list_users(self)
+ for i,user in ipairs(users) do
+ if userpermissions.value.userid.value == user then
+ userpermissions.value.userid.errtxt = nil
+ success = true
+ break
+ end
+ end
+ success = validatepermissions(userpermissions) and success
+ return success, userpermissions
+end
+
+local function validaterolepermissions(self, rolepermissions)
+ local success = false
+ rolepermissions.value.role.errtxt = "Invalid role"
+ local rols = roles.list_all_roles(self)
+ for i,role in ipairs(rols) do
+ if rolepermissions.value.role.value == role then
+ rolepermissions.value.role.errtxt = nil
+ success = true
+ break
+ end
+ end
+ success = validatepermissions(rolepermissions) and success
+ return success, rolepermissions
+end
+
+function getuserpermissions(self, userid)
+ local entry = authenticator.auth.read_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, userid) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+ local allowed = cfe({ type="list", value=allowedlist, label="DID Permissions", descr="List one DID per line" })
+ local restrict = cfe({ type="boolean", value=restricted, label="Enable Restrictions" })
+ local user = cfe({ value=userid, label="User Name" })
+ local output = cfe({ type="group", value={userid=user, allowed=allowed, restricted=restrict}, label="DID Permissions" })
+ validateuserpermissions(self, output)
+ return output
+end
+
+function setuserpermissions(self, userpermissions)
+ local success, userpermissions = validateuserpermissions(self, userpermissions)
+
+ if success then
+ authenticator.auth.write_entry(self, authenticator.usertable, self.conf.prefix..self.conf.controller, userpermissions.value.userid.value, tostring(userpermissions.value.restricted.value)..":"..(table.concat(userpermissions.value.allowed.value, ",") or ""))
+ else
+ userpermissions.errtxt = "Failed to set user permissions"
+ end
+ return userpermissions
+end
+
+function getrolepermissions(self, role)
+ local entry = authenticator.auth.read_entry(self, authenticator.roletable, self.conf.prefix..self.conf.controller, role) or ""
+ local restricted, allowedlist
+ restricted, allowedlist = parseentry(entry)
+ local allowed = cfe({ type="list", value=allowedlist, label="DID Permissions", descr="List one DID per line" })
+ local restrict = cfe({ type="boolean", value=restricted, label="Enable Restrictions" })
+ local rol = cfe({ value=role, label="Role" })
+ local output = cfe({ type="group", value={role=rol, allowed=allowed, restricted=restrict}, label="DID Permissions" })
+ validaterolepermissions(self, output)
+ return output
+end
+
+function setrolepermissions(self, rolepermissions)
+ local success, rolepermissions = validaterolepermissions(self, rolepermissions)
+
+ if success then
+ authenticator.auth.write_entry(self, authenticator.roletable, self.conf.prefix..self.conf.controller, rolepermissions.value.role.value, tostring(rolepermissions.value.restricted.value)..":"..(table.concat(rolepermissions.value.allowed.value, ",") or ""))
+ else
+ rolepermissions.errtxt = "Failed to set role permissions"
+ end
+ return rolepermissions
+end