diff options
-rw-r--r-- | app/Makefile | 4 | ||||
-rwxr-xr-x | app/acf-util/password-controller.lua | 18 | ||||
-rwxr-xr-x | app/acf-util/password-html.lsp | 1 | ||||
-rwxr-xr-x | app/acf-util/password-model.lua | 6 | ||||
-rw-r--r-- | app/acf-util/roles-controller.lua | 113 | ||||
-rw-r--r-- | app/acf-util/roles-editrole-html.lsp | 20 | ||||
-rw-r--r-- | app/acf-util/roles-html.lsp | 20 | ||||
-rw-r--r-- | app/acf-util/roles-newrole-html.lsp | 20 | ||||
-rw-r--r-- | app/acf-util/roles-viewroles-html.lsp | 43 | ||||
-rwxr-xr-x | app/acf-util/roles.menu | 4 | ||||
-rw-r--r-- | app/acf_www-controller.lua | 14 | ||||
-rw-r--r-- | lib/authenticator-plaintext.lua | 12 | ||||
-rw-r--r-- | lib/roles.lua | 123 | ||||
-rw-r--r-- | lib/viewfunctions.lua | 2 | ||||
-rw-r--r-- | roles | 2 |
15 files changed, 352 insertions, 50 deletions
diff --git a/app/Makefile b/app/Makefile index f7e42dc..ffa03ed 100644 --- a/app/Makefile +++ b/app/Makefile @@ -8,6 +8,10 @@ APP_DIST= \ acf-util/roles-controller.lua \ acf-util/roles-model.lua \ acf-util/roles-html.lsp \ + acf-util/roles-viewroles-html.lsp \ + acf-util/roles-editrole-html.lsp \ + acf-util/roles-newrole-html.lsp \ + acf-util/roles.menu \ acf-util/password-controller.lua \ acf-util/password-html.lsp \ acf-util/password-model.lua \ diff --git a/app/acf-util/password-controller.lua b/app/acf-util/password-controller.lua index 1d3aa7a..809e766 100755 --- a/app/acf-util/password-controller.lua +++ b/app/acf-util/password-controller.lua @@ -29,15 +29,6 @@ function edituser(self) if self.clientdata.password == "" then self.clientdata.password = nil end if self.clientdata.password_confirm == "" then self.clientdata.password_confirm = nil end - -- FIXME this is because multi selects don't work in haserl - if self.clientdata.roles then - local newroles = {} - for x,role in pairs(self.clientdata.roles) do - newroles[#newroles + 1] = role - end - self.clientdata.roles = newroles - end - -- Update userinfo local output = self.model.update_user(self, self.clientdata, false) @@ -51,15 +42,6 @@ function edituser(self) end function newuser(self) - -- FIXME this is because multi selects don't work in haserl - if self.clientdata.roles then - local newroles = {} - for x,role in pairs(self.clientdata.roles) do - newroles[#newroles + 1] = role - end - self.clientdata.roles = newroles - end - -- Update userinfo local output = self.model.update_user(self, self.clientdata, true) diff --git a/app/acf-util/password-html.lsp b/app/acf-util/password-html.lsp index a11d9e3..9de2d4f 100755 --- a/app/acf-util/password-html.lsp +++ b/app/acf-util/password-html.lsp @@ -4,7 +4,6 @@ --[[ DEBUG INFORMATION io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>") io.write(html.cfe_unpack(form)) -io.write(html.cfe_unpack(ENV)) io.write(html.cfe_unpack(FORM)) io.write("</span>") --]] diff --git a/app/acf-util/password-model.lua b/app/acf-util/password-model.lua index 553abca..e3d58f1 100755 --- a/app/acf-util/password-model.lua +++ b/app/acf-util/password-model.lua @@ -37,9 +37,6 @@ function update_user(self, clientdata, newuser) end userinfo = userinfo or {} - -- Get list of available roles - local avail_roles=auth.list_roles() - config.userid = cfe({ label="User id", value=(userinfo.userid or clientdata.userid or ""), @@ -54,7 +51,7 @@ function update_user(self, clientdata, newuser) label="Roles", value=(userinfo.roles or clientdata.roles or {}), type="multi", - option=avail_roles, + option=auth.list_roles(), errtxt = errormessage.roles }) config.password = cfe({ @@ -73,6 +70,7 @@ function get_users(self) --List all users and their userinfo local users = {} local userlist = auth.list_users(self) + for x,user in pairs(userlist) do local userinfo = auth.get_userinfo(self,user) users[user] = cfe({ diff --git a/app/acf-util/roles-controller.lua b/app/acf-util/roles-controller.lua index 4363cb6..1d69b8b 100644 --- a/app/acf-util/roles-controller.lua +++ b/app/acf-util/roles-controller.lua @@ -5,6 +5,25 @@ module (..., package.seeall) auth = require("authenticator-plaintext") roll = require("roles") +local get_all_permissions = function(self) + -- need to get a list of all the controllers + controllers = roles.get_controllers(self) + local table_perm = {} + local array_perm = {} + for a,b in pairs(controllers) do + if nil == table_perm[b.sname] then + table_perm[b.sname] = {} + end + temp = roles.get_controllers_func(self,b) + for x,y in ipairs(temp) do + table_perm[b.sname][y] = {} + array_perm[#array_perm + 1] = b.sname .. ":" .. y + end + end + + return table_perm, array_perm +end + default_action = "read" -- Return your own roles/permissions @@ -16,7 +35,7 @@ read = function(self) end -- Return roles/permissions for specified user -viewroles = function(self) +viewuserroles = function(self) if not (self.clientdata.userid) then redirect(self) end @@ -27,7 +46,7 @@ viewroles = function(self) end -- Return permissions for specified role -viewperms = function(self) +viewroleperms = function(self) if not (self.clientdata.role) then redirect(self, "getlist") end @@ -37,6 +56,92 @@ viewperms = function(self) end -- Return list of all permissions -getlist = function(self) - return cfe({ type="group", value={permissions=self.model:getcont(self)} }) +getpermslist = function(self) + permissions = cfe({ type="table", value=get_all_permissions(self), label="All Permissions" }) + return cfe({ type="group", value={permissions=permissions} }) +end + +viewroles = function(self) + -- Get command result out of session data + local cmdresult = self.sessiondata.cmdresult + self.sessiondata.cmdresult = nil + + local defined_roles, default_roles = roll.list_roles() + local defined_roles_cfe=cfe({ type="list", value=defined_roles, label="Locally-defined roles" }) + local default_roles_cfe=cfe({ type="list", value=default_roles, label="System-defined roles" }) + + return cfe({ type="group", value={defined_roles=defined_roles_cfe, default_roles=default_roles_cfe, cmdresult=cmdresult} }) +end + +local setpermissions = function(self, role, permissions, newrole) + local errtxt + local my_perms = {} + if permissions then + -- we're changing permissions + local result = true + if newrole then + -- make sure not overwriting role + for x,ro in ipairs(roles.list_roles()) do + if role==ro then + result = false + errtxt = "Role already exists" + break + end + end + end + if result==true then + result, errtxt = roles.set_role_perm(role, nil, permissions) + end + my_perms = self.clientdata.permissions + else + if role then + tmp, my_perms = roles.get_role_perm(self.conf.appdir, role) + else + role = "" + end + end + + local tmp, all_perms = get_all_permissions(self) + table.sort(all_perms) + + local permissions_cfe = cfe({ type="multi", value=my_perms, option=all_perms, label="Role permissions" }) + local role_cfe = cfe({ value=role, label="Role", errtxt=errtxt }) + + return cfe({ type="table", value={role=role_cfe, permissions=permissions_cfe} }) +end + +newrole = function(self) + local form = setpermissions(self, self.clientdata.role, self.clientdata.permissions, true) + form.type = "form" + form.label = "Edit new role" + if form.value.role.errtxt then + form.errtxt = "Failed to create role" + elseif self.clientdata.permissions then + -- If we have permissions, we tried to set + local cmdresult = cfe({ value="New role created" }) + self.sessiondata.cmdresult = cmdresult + redirect(self, "viewroles") + end + return form +end + +editrole = function(self) + local form = setpermissions(self, self.clientdata.role, self.clientdata.permissions, false) + form.type = "form" + form.label = "Edit role" + if form.value.role.errtxt then + form.errtxt = "Failed to save role" + elseif self.clientdata.permissions then + -- If we have permissions, we tried to set + local cmdresult = cfe({ value="Role saved" }) + self.sessiondata.cmdresult = cmdresult + redirect(self, "viewroles") + end + return form +end + +deleterole = function(self) + local result, cmdresult = roles.delete_role(self.clientdata.role) + self.sessiondata.cmdresult = cfe({ value=cmdresult }) + redirect(self, "viewroles") end diff --git a/app/acf-util/roles-editrole-html.lsp b/app/acf-util/roles-editrole-html.lsp new file mode 100644 index 0000000..bf42f28 --- /dev/null +++ b/app/acf-util/roles-editrole-html.lsp @@ -0,0 +1,20 @@ +<? local form= ... ?> +<? --[[ + io.write(html.cfe_unpack(form)) + io.write(html.cfe_unpack(FORM)) +--]] ?> + +<? ---[[ ?> +<H1><?= form.label ?></H1> +<? + require("viewfunctions") + form.action = "" + form.submit = "Save" + -- If editing existing role, disable role + if form.value.role and "GET" == ENV["REQUEST_METHOD"] then + form.value.role.contenteditable = false + end + local order = { "role", "permissions" } + displayform(form, order) +?> +<? --]] ?> diff --git a/app/acf-util/roles-html.lsp b/app/acf-util/roles-html.lsp index 4a23c25..2f4c8b1 100644 --- a/app/acf-util/roles-html.lsp +++ b/app/acf-util/roles-html.lsp @@ -27,10 +27,22 @@ <? elseif view.value.role then ?> <H2><?= view.value.role.value ?>'s full permissions are</H2> <? end ?> - <? for x,cont in pairs(view.value.permissions.value) do - print("<b>",x,"</b>") - for y,act in pairs(cont) do - print(y) + <? local controllers = {} + -- It's nice to have it in alphabetical order + for cont in pairs(view.value.permissions.value) do + controllers[#controllers + 1] = cont + end + table.sort(controllers) + for x,cont in ipairs(controllers) do + print("<b>",cont,"</b>") + -- Again, alphabetical order + local actions = {} + for act in pairs(view.value.permissions.value[cont]) do + actions[#actions + 1] = act + end + table.sort(actions) + for y,act in pairs(actions) do + print(act) end print("<br>") end ?> diff --git a/app/acf-util/roles-newrole-html.lsp b/app/acf-util/roles-newrole-html.lsp new file mode 100644 index 0000000..bf42f28 --- /dev/null +++ b/app/acf-util/roles-newrole-html.lsp @@ -0,0 +1,20 @@ +<? local form= ... ?> +<? --[[ + io.write(html.cfe_unpack(form)) + io.write(html.cfe_unpack(FORM)) +--]] ?> + +<? ---[[ ?> +<H1><?= form.label ?></H1> +<? + require("viewfunctions") + form.action = "" + form.submit = "Save" + -- If editing existing role, disable role + if form.value.role and "GET" == ENV["REQUEST_METHOD"] then + form.value.role.contenteditable = false + end + local order = { "role", "permissions" } + displayform(form, order) +?> +<? --]] ?> diff --git a/app/acf-util/roles-viewroles-html.lsp b/app/acf-util/roles-viewroles-html.lsp new file mode 100644 index 0000000..a98f5b9 --- /dev/null +++ b/app/acf-util/roles-viewroles-html.lsp @@ -0,0 +1,43 @@ +<? local view= ... ?> +<? --[[ + io.write(html.cfe_unpack(view)) +--]] ?> + +<? ---[[ ?> +<H1>ROLES</H1> + +<? if view.value.cmdresult then ?> +<H2>Command Result</H2> +<dl><?= view.value.cmdresult.value ?></dl> +<? end ?> + +<H2>Create new role</H2> +<form action="newrole" method="POST"> +<dl><dt><input class="submit" type="submit" value="New Role"></dt></dl> +</form> + +<H2>Existing roles</H2> +<? if view.value.default_roles then ?> + <dl> + <? for x,role in pairs(view.value.default_roles.value) do ?> + <dt><img src='/static/tango/16x16/categories/applications-system.png' height='16' width='16'> <?= role ?></dt> + <dd> + [<a href='viewroleperms?role=<?= role ?>'>View this role</a>] + </dd> + <? end ?> + </dl> +<? end ?> +<? if view.value.defined_roles then ?> + <dl> + <? table.sort(view.value.defined_roles.value) ?> + <? for x,role in pairs(view.value.defined_roles.value) do ?> + <dt><img src='/static/tango/16x16/apps/system-users.png' height='16' width='16'> <?= role ?></dt> + <dd> + [<a href='viewroleperms?role=<?= role ?>'>View this role</a>] + [<a href='editrole?role=<?= role ?>'>Edit this role</a>] + [<a href='deleterole?role=<?= role ?>'>Delete this role</a>] + </dd> + <? end ?> + </dl> +<? end ?> +<? --]] ?> diff --git a/app/acf-util/roles.menu b/app/acf-util/roles.menu new file mode 100755 index 0000000..7bcca30 --- /dev/null +++ b/app/acf-util/roles.menu @@ -0,0 +1,4 @@ +#CAT GROUP/DESC TAB ACTION +System 02Roles_management Administration viewroles +System 02Roles_management My_Roles read + diff --git a/app/acf_www-controller.lua b/app/acf_www-controller.lua index 98b732f..67e95ad 100644 --- a/app/acf_www-controller.lua +++ b/app/acf_www-controller.lua @@ -75,6 +75,20 @@ mvc.on_load = function (self, parent) self.clientdata = FORM self.conf.clientip = ENV.REMOTE_ADDR + -- FIXME this is because multi selects don't work in haserl + for name,oldtable in pairs(self.clientdata) do + if type(oldtable) == "table" then + -- Assume it's a sparse array, and remove blanks + local newtable={} + for x=1,table.maxn(oldtable) do + if oldtable[x] then + newtable[#newtable + 1] = oldtable[x] + end + end + self.clientdata[name] = newtable + end + end + parent_exception_handler = parent.exception_handler -- this sets the package path for us and our children diff --git a/lib/authenticator-plaintext.lua b/lib/authenticator-plaintext.lua index c68ec2b..6c4cbbd 100644 --- a/lib/authenticator-plaintext.lua +++ b/lib/authenticator-plaintext.lua @@ -12,6 +12,7 @@ userid:password:username:role1[,role2...] module (..., package.seeall) local sess = require ("session") +require("roles") local pvt={} @@ -181,8 +182,15 @@ list_users = function (self) end list_roles = function (self) - local output = {"CREATE","UPDATE","DELETE","READ"} - return output + -- Get list of available roles (everything except ALL) + local avail_roles = roles.list_all_roles() + for x,role in ipairs(avail_roles) do + if role=="ALL" then + table.remove(avail_roles,x) + break + end + end + return avail_roles end change_setting = function (self, userid, parameter, value) diff --git a/lib/roles.lua b/lib/roles.lua index 768e96f..53409c0 100644 --- a/lib/roles.lua +++ b/lib/roles.lua @@ -7,12 +7,28 @@ require ("format") module (..., package.seeall) +local roles_file = "/etc/acf/roles" +local default_roles = { "CREATE", "UPDATE", "DELETE", "READ", "ALL" } + +-- returns a table of the *.roles files +-- startdir should be the app dir +local get_roles_candidates = function (startdir) + local t = {} + local fh = io.popen('find ' .. startdir .. ' -name "*.roles"') + for x in fh:lines() do + t[#t + 1] = x + end + return t +end + -- Return a list of *controller.lua files list_controllers = function(self) local list = {} local f = io.popen("/usr/bin/find /usr/share/acf/ |/bin/grep \"controller.lua$\" ") for a in f:lines() do - list[#list + 1 ] = a + if not string.find(a, "acf_") then + list[#list + 1 ] = a + end end f:close() return list @@ -58,24 +74,45 @@ get_controllers_func = function(self,controller_info) end end --- returns a table of the *.roles files --- startdir should be the app dir -local get_roles_candidates = function (startdir) - local t = {} - local fh = io.popen('find ' .. startdir .. ' -name "*.roles"') - for x in fh:lines() do - t[#t + 1] = x +list_default_roles = function() + return default_roles +end + +list_roles = function() + local defined_roles = {} + local reverseroles = {} + for x,role in ipairs(default_roles) do + reverseroles[role] = x end - return t + + -- Open the roles file and parse for defined roles + f = fs.read_file_as_array(roles_file) + for x,line in pairs(f) do + temprole = string.match(line,"^[%a]+") + if not reverseroles[temprole] then + defined_roles[#defined_roles + 1] = temprole + end + end + + return defined_roles, default_roles end +list_all_roles = function() + local defined_roles, default_roles = list_roles() + for x,role in ipairs(defined_roles) do + default_roles[#default_roles + 1] = role + end + return default_roles +end + -- Go through the roles files and determine the permissions for the specified roles get_roles_perm = function(startdir,roles) permissions = {} + permissions_array = {} -- find all of the roles files and add in the master file local rolesfiles = get_roles_candidates(startdir) - rolesfiles[#rolesfiles + 1] = "/etc/acf/roles" + rolesfiles[#rolesfiles + 1] = roles_file local reverseroles = {} for x,role in ipairs(roles) do @@ -94,8 +131,9 @@ get_roles_perm = function(startdir,roles) if nil == permissions[control] then permissions[control] = {} end - if action and nil == permissions[control][action] then + if action then permissions[control][action] = {} + permissions_array[#permissions_array + 1] = control .. ":" .. action end end end @@ -103,16 +141,17 @@ get_roles_perm = function(startdir,roles) end end - return permissions + return permissions, permissions_array end -- Go through the roles files and determine the permissions for the specified role get_role_perm = function(startdir,role) permissions = {} + permissions_array = {} -- find all of the roles files and add in the master file local rolesfiles = get_roles_candidates(startdir) - rolesfiles[#rolesfiles + 1] = "/etc/acf/roles" + rolesfiles[#rolesfiles + 1] = roles_file for x,file in ipairs(rolesfiles) do f = fs.read_file_as_array(file) @@ -125,8 +164,9 @@ get_role_perm = function(startdir,role) if nil == permissions[control] then permissions[control] = {} end - if action and nil == permissions[control][action] then + if action then permissions[control][action] = {} + permissions_array[#permissions_array + 1] = control .. ":" .. action end end end @@ -134,6 +174,59 @@ get_role_perm = function(startdir,role) end end - return permissions + return permissions, permissions_array +end + +-- Delete a role from role file +delete_role = function(role) + for x,ro in ipairs(default_roles) do + if role==ro then + return false, "Cannot delete default roles" + end + end + local rolecontent = fs.read_file_as_array(roles_file) + local output = {} + local result = false + local cmdresult = "Role entry not found" + for x,line in pairs(rolecontent) do + if not string.match(line, "^" .. role .. "=") then + table.insert(output,line) + else + result = true + cmdresult = "Role deleted" + end + end + + if result == true then + fs.write_file(roles_file, table.concat(output,"\n")) + end + + return result, cmdresult end +-- Set permissions for a role in role file +set_role_perm = function(role, permissions, permissions_array) + if role==nil or role=="" then + return false, "Invalid Role" + end + for x,ro in ipairs(default_roles) do + if role==ro then + return false, "Cannot modify default roles" + end + end + if permissions and not permissions_array then + permissions_array = {} + for cont,actions in pairs(permissions) do + for action in pairs(actions) do + permissions_array[#permissions_array + 1] = cont .. ":" .. action + end + end + end + if permissions_array==nil or #permissions_array==0 then + return false, "No permissions set" + end + + delete_role(role) + fs.write_line_file(roles_file, role .. "=" .. table.concat(permissions_array,",")) + return true +end diff --git a/lib/viewfunctions.lua b/lib/viewfunctions.lua index c7aa53f..5080a34 100644 --- a/lib/viewfunctions.lua +++ b/lib/viewfunctions.lua @@ -99,7 +99,7 @@ function displayitem(myitem, viewtype) for x,val in ipairs(myitem.option) do myitem.value = val myitem.checked = reverseval[val] - myitem.name = tempname .. "." .. val + myitem.name = tempname .. "." .. x io.write(html.form.checkbox(myitem) .. val .. "<br>\n") end myitem.name = tempname @@ -1,3 +1,3 @@ ALL=welcome:read,logon:logon,logon:logout,logon:status -CREATE=password:status,password:edituser,password:newuser,password:deleteuser,roles:getlist,roles:viewroles,roles:viewperms +CREATE=password:status,password:edituser,password:newuser,password:deleteuser,roles:getpermslist,roles:viewuserroles,roles:viewroleperms,roles:viewroles,roles:editrole,roles:deleterole,roles:newrole READ=password:editme,roles:read |