diff options
author | Ted Trask <ttrask01@yahoo.com> | 2008-04-30 20:36:02 +0000 |
---|---|---|
committer | Ted Trask <ttrask01@yahoo.com> | 2008-04-30 20:36:02 +0000 |
commit | 378e53f20a0f11c36afffbaef78f47a5303df9ce (patch) | |
tree | a39e3c216dc10f919ef272c53b67a8f01f001be0 | |
parent | 82fd96bdcc5b721d8fc208fe4edba54f4dc6fdb7 (diff) | |
download | acf-core-378e53f20a0f11c36afffbaef78f47a5303df9ce.tar.bz2 acf-core-378e53f20a0f11c36afffbaef78f47a5303df9ce.tar.xz |
Modified cfe, removing option, errtxt, and name, and adding label - This may break things.
Rewrote password module, adding model
Modified authenticator to make password module work
git-svn-id: svn://svn.alpinelinux.org/acf/core/trunk@1052 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r-- | app/Makefile | 1 | ||||
-rw-r--r-- | app/acf-util/logon-controller.lua | 8 | ||||
-rw-r--r-- | app/acf-util/logon-html.lsp | 21 | ||||
-rw-r--r-- | app/acf-util/logon-model.lua | 6 | ||||
-rwxr-xr-x | app/acf-util/password-controller.lua | 382 | ||||
-rwxr-xr-x | app/acf-util/password-html.lsp | 74 | ||||
-rwxr-xr-x | app/acf-util/password-status-html.lsp | 92 | ||||
-rw-r--r-- | app/acf_cli-controller.lua | 6 | ||||
-rw-r--r-- | app/acf_www-controller.lua | 7 | ||||
-rw-r--r-- | lib/authenticator-plaintext.lua | 148 | ||||
-rw-r--r-- | lib/html.lua | 22 | ||||
-rw-r--r-- | lib/viewfunctions.lua | 109 | ||||
-rw-r--r-- | roles | 4 |
13 files changed, 332 insertions, 548 deletions
diff --git a/app/Makefile b/app/Makefile index b71b10f..cdd42bb 100644 --- a/app/Makefile +++ b/app/Makefile @@ -11,6 +11,7 @@ APP_DIST= \ acf-util/roles-read-html.lsp \ acf-util/password-controller.lua \ acf-util/password-html.lsp \ + acf-util/password-model.lua \ acf-util/password-status-html.lsp \ acf-util/password.menu \ acf_www-controller.lua\ diff --git a/app/acf-util/logon-controller.lua b/app/acf-util/logon-controller.lua index 7d4447b..1dc3360 100644 --- a/app/acf-util/logon-controller.lua +++ b/app/acf-util/logon-controller.lua @@ -6,7 +6,9 @@ default_action = "status" -- Logon a new user based upon id and password in clientdata logon = function(self) - local cmdresult = cfe({ value=clientdata.userid or "", name="User ID" }) + local userid = cfe({ value=clientdata.userid or "", label="User ID" }) + local password = cfe({ label="Password" }) + local cmdresult = cfe({ type="form", value={userid=userid, password=password}, label="Logon" }) if clientdata.userid and clientdata.password then local logon = self.model:logon(clientdata, conf.clientip, conf.sessiondir, sessiondata) -- If successful logon, redirect to status, otherwise try again @@ -28,8 +30,8 @@ end -- Report the login status status = function(self) - local name = cfe({ name="User Name" }) - local sessionid = cfe({ value=self.sessiondata.id or "", name="Session ID" }) + local name = cfe({ label="User Name" }) + local sessionid = cfe({ value=self.sessiondata.id or "", label="Session ID" }) if self.sessiondata.userinfo then name.value = self.sessiondata.userinfo.username or "" end diff --git a/app/acf-util/logon-html.lsp b/app/acf-util/logon-html.lsp index 20aa0ee..f503a9b 100644 --- a/app/acf-util/logon-html.lsp +++ b/app/acf-util/logon-html.lsp @@ -1,20 +1,19 @@ <? local form = ... ?> +<? require("viewfunctions") ?> <? --[[ io.write(html.cfe_unpack(form)) --]] ?> -<? if form.errtxt ~= "" then ?> +<? if form.errtxt then ?> <h1>Command Result</h1> <p class='error'> <?= form.errtxt ?></p> <? end ?> -<h1>Logon</h1> -<form action="logon" method="POST"> -<DL> - <DT>User id</DT> - <DD><input class="text" type="text" name="userid" value="<?= form.value ?>"></DD> - <DT>Password</DT> - <DD><input class="password" type="password" name="password" value=""></DD> - <DT><input class="submit" type="submit" name="Logon" value="Logon"></DD> -</DL> -</form> +<h1><?= form.label ?></h1> +<? + form.action = "logon" + form.submit = "Logon" + form.value.password.type = "password" + local order = { "userid", "password" } + displayform(form, order) +?> diff --git a/app/acf-util/logon-model.lua b/app/acf-util/logon-model.lua index 7e8a21e..16e9f7f 100644 --- a/app/acf-util/logon-model.lua +++ b/app/acf-util/logon-model.lua @@ -29,7 +29,7 @@ logoff = function (sessiondir, sessiondata) sessiondata[a] = nil end - return cfe({ type="boolean", value=success, name="Logoff Success" }) + return cfe({ type="boolean", value=success, label="Logoff Success" }) end -- Log on new user if possible and set up userinfo in session @@ -57,12 +57,12 @@ logon = function (self, clientdata, ip_addr, sessiondir, sessiondata) sessiondata.id = session.random_hash(512) local t = auth.get_userinfo (self, clientdata.userid) sessiondata.userinfo = t or {} - return cfe({ type="boolean", value=true, name="Logon Success" }) + return cfe({ type="boolean", value=true, label="Logon Success" }) else -- We have a bad login, log the event session.record_event(sessiondir, clientdata.userid, session.hash_ip_addr(ip_addr)) end end - return cfe({ type="boolean", value=false, name="Logon Success" }) + return cfe({ type="boolean", value=false, label="Logon Success" }) end diff --git a/app/acf-util/password-controller.lua b/app/acf-util/password-controller.lua index 4dbe1eb..1d3aa7a 100755 --- a/app/acf-util/password-controller.lua +++ b/app/acf-util/password-controller.lua @@ -1,360 +1,78 @@ module(..., package.seeall) -local auth=require("authenticator-plaintext") - -default_action = "status" - -local function admin_permission() --- if (sessiondata.userinfo) and (sessiondata.userinfo.userid == "alpine") then - return true --- else --- return false --- end -end - -local function check_logonstatus(self) - -- Redirect the user if he's not logged in. - if not (self.sessiondata.userinfo) then - redirect(self, "logon", "logon") - end -end - -local function get_config(self,userid) - local config = {} - local userinfo = {} - if (#userid > 0) then - userinfo=auth.get_userinfo(self,userid) - end - if not (userinfo) then - userinfo = {userid = "", username = "", roles = {} } - end - - -- Get list of available roles - local avail_roles=auth.list_roles() - --- config.debug = userid -- Debug info - - config.userid = cfe({ - name="userid", - label="User id", - value=(userinfo.userid or ""), - }) - config.orguserid = cfe({ - name="orguserid", - value=(userinfo.userid or ""), - type="hidden", - }) - config.username = cfe({ - name="username", - label="Real name", - value=userinfo.username, - }) - config.roles = cfe({ - name="roles", - label="Roles", - option=userinfo.roles, - type="select", - size=#avail_roles, - }) - config.password = cfe({ - name="password", - label="Password", - type="passwd", - }) - config.password_confirm = cfe({ - name="password_confirm", - label="Password (confirm)", - type="passwd", - }) - - config.availableroles = cfe({ - name="availableroles", - label="Available roles", - type="select", - option=avail_roles, - }) - - return config -end +default_action = "editme" function status(self) - - -- Redirect the user if he's not logged in. - check_logonstatus(self) - - local status = {} - - -- Check for admin persmissions - else redirect to personal options - if not (admin_permission()) then - self.conf.action = "editme" - return editme(self) - end - - -- Redirect when creating a new account - if (clientdata.cmdnew) then - self.conf.action = "administrator" - self.conf.type = "redir" - - return administrator(self) - end - - --List all users and their userinfo - status.users = {} - local userlist = auth.list_users(self) - for k,v in pairs(userlist) do - local userinfo = auth.get_userinfo(self,v) - status.users[k] = cfe({ - name=v, - label=v, --- debug=userinfo, -- Debug info - value={ userid=cfe ({ - name="userid", - label="User ID", - value=userinfo.userid, - }), - username=cfe ({ - name="username", - label="Real name", - value=userinfo.username, - }), - roles=cfe ({ - name="roles", - label="Roles", - value=table.concat(userinfo.roles," / "), - option=userinfo.roles, - type="select", - }), - }, - - }) - local errormessage = "" - -- Check if this user has got any errors in the config - if (userinfo.password == "") or (userinfo.password == nil) then - errormessage = "This user has no password! ".. errormessage - end - -- Check if user has no roles - if (table.maxn(userinfo.roles) == 0) then - errormessage = "This user has no roles! " .. errormessage - end - -- If there where any errormessages, then present them - if (#errormessage > 0) then - status.users[k].value.errors = cfe ({ - name="errors", - label="Attention", - value=errormessage, - }) - end - end - - --Create a button for 'New user account' - status.cmdnew = cfe ({ - name="cmdnew", - type="submit", - label="Create new account", - value="Create", --- disabled="yes", - }) - return { status=status } -end - -function administrator(self) - - -- Redirect the user if he's not logged in. - check_logonstatus(self) - - local output = {} - - -- Check for admin persmissions - else redirect to personal options - if not (admin_permission()) then - self.conf.action = "editme" - self.conf.type = "redir" - return editme(self) - end - - -- Output userinfo - output = get_config(self,(self.clientdata.orguserid or self.clientdata.userid or "")) - - -- Clear password-field - output.password.value = "" - - -- Add some buttons - output.cmdsave = cfe ({ - name="cmdsave", - type="submit", - label="Save changes", - value="Save", - }) - output.cmddelete = cfe ({ - name="cmddelete", - type="submit", - label="Delete this account", - value="Delete", - }) - - return {config=output} + return self.model.get_users(self) end function editme(self) + -- just to make sure can't modify any other user from this action + self.clientdata.userid = sessiondata.userinfo.userid + self.clientdata.roles = nil + -- if password is blank, don't update it or require it + if self.clientdata.password == "" then self.clientdata.password = nil end + if self.clientdata.password_confirm == "" then self.clientdata.password_confirm = nil end - -- Redirect the user if he's not logged in. - check_logonstatus(self) - - -- Output userinfo - local output = get_config(self,sessiondata.userinfo.userid) + -- Update userinfo + local output = self.model.update_user(self, self.clientdata, false) - -- Hide roles/cmddelete for current the user - output.roles = nil - output.cmddelete = nil + -- Don't allow changing of roles for yourself + output.value.roles = nil - -- Disable userid - output.userid.disabled = "yes" - - -- Set userid - output.orguserid.value = self.sessiondata.userinfo.userid - - -- Add save-button - output.cmdsave = cfe ({ - name="cmdsave", - type="submit", - label="Save changes", - value="Save", - }) - - return {config=output} + output.label = "Edit My Settings" + return output end -local clientdata_from_roles = function(self) - local output = {} +function edituser(self) + -- if password is blank, don't update it or require it + if self.clientdata.password == "" then self.clientdata.password = nil end + if self.clientdata.password_confirm == "" then self.clientdata.password_confirm = nil end - for k,v in pairs(auth.list_roles()) do - if (self.clientdata[v]) then - table.insert(output, v) + -- 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 - - return output -end - -function save(self) - -- Redirect the user if he's not logged in. - check_logonstatus(self) - - local errormessage = {} - local cmdresult = {} - -- FIXME: Check if user is allowed to save settings - -- FIXME: If user has little priviliges, then see to that he only can change hes own settings - -- At the moment... the user could send self.clientdata.orguserid = 'someoneelseid' and change hes settings. - -- This field is hidden for user... but advanced users could probably workaround somehow. + -- Update userinfo + local output = self.model.update_user(self, self.clientdata, false) - -- Delete selected user - if (clientdata.cmddelete) then - cmdresult["delete"],errormessage["delete"] = auth.delete_user(self,self.clientdata.orguserid) + -- result + if output.descr and output.errtxt == nil then + redirect(self, "status") end - -- If userid-filed is disabled, then use orguserid instead (hidden filed) - if not (self.clientdata.userid) then - self.clientdata.userid = self.clientdata.orguserid - end - - -- We start changing things based on input - if (clientdata.cmdsave) then - -- Check if password is written correct - if (self.clientdata.password == self.clientdata.password_confirm) and - (#self.clientdata.userid > 0) then - -- Check if we are editing a existing user or creating a new one - if (#clientdata.orguserid > 0) then - local variables="username userid roles" - -- Change password if user entered any values - if (#self.clientdata.password > 0) then - variables = variables .. " password" - end - -- Concate roles into one chunk of data (needed by the model) - self.clientdata.roles = table.concat(clientdata_from_roles(self), ",") + output.label = "Edit User Settings" + return output +end --- cmdresult.debugs = self.clientdata.orguserid -- Debug information - for var in string.gmatch(variables, "%S+") do - if (self.clientdata[var]) then - cmdresult["cmdtype"] = "change" - cmdresult[var],errormessage[var] = auth.change_settings( - self, - self.clientdata.orguserid, - var, self.clientdata[var] - ) - end - end - else - -- We are about to create a new user - cmdresult["cmdtype"] = "new" - cmdresult["new"],errormessage["new"] = auth.new_settings( - self, - self.clientdata.userid, - self.clientdata.username, - self.clientdata.password, - self.clientdata.password_confirm, - clientdata_from_roles(self) - ) - end - elseif (self.clientdata.password ~= self.clientdata.password_confirm) then - errormessage.none = {password_confirm = "You entered wrong password/confirmation"} - elseif (#self.clientdata.userid == 0) then - errormessage.none = {userid = "Userid can not be blank!"} +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 - -- Fetch saved values - local output = administrator(self) + -- Update userinfo + local output = self.model.update_user(self, self.clientdata, true) - -- Report errors from previously entered values (present this error for the user) - if (cmdresult["cmdtype"] == "new") then - -- Report where the user entered som errors - for k,v in pairs(errormessage["new"]) do - output.config[k].errtxt = v - end - else - -- Report where the user entered som errors - for k,v in pairs(errormessage) do - for kk,vv in pairs(v) do - output.config[kk].errtxt = vv - end - end + -- result + if output.descr and output.errtxt == nil then + redirect(self, "status") end - -- If there was any errormessage then return to previous page and present the errormessage - for k,v in pairs(errormessage) do - for kk,vv in pairs(v) do - - -- Incase we entered some invalid options, but entered correct Password (and it has been changed) - -- then inform the user that the password has been changed - if (cmdresult.password) then - output.config.password.descr = "* Password has been changed!" - end - - -- Write the previously entered information on the screen. - for k,v in pairs(self.clientdata) do - if (output.config[k]) and (k == roles) then - table.insert(output.config[k].option, v) - elseif (output.config[k]) then - output.config[k].value = v - end - end - - -- Because something went wrong... clear the password and let the user re-enter the password/confirmation - output.config.password.value = "" - output.config.password_confirm.value = "" - - -- Debug information --- output.config.debugcmdresult = cmdresult -- Debug information - - -- Redirect page - self.conf.action = "administrator" - self.conf.type = "redir" - return output - end - end + output.label = "New User Settings" + return output +end - --If everything went OK then redirect to main page - self.conf.action = "status" - self.conf.type = "redir" - return status(self) +function deleteuser(self) + self.model.delete_user(self, self.clientdata.userid) + redirect(self, "status") end diff --git a/app/acf-util/password-html.lsp b/app/acf-util/password-html.lsp index 5d4d488..a11d9e3 100755 --- a/app/acf-util/password-html.lsp +++ b/app/acf-util/password-html.lsp @@ -1,72 +1,30 @@ <? local form = ... ?> +<? require("viewfunctions") ?> <? --[[ 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>") --]] ?> -<? -function displayinfo(myform,tags,viewtype) - io.write("\n<DL>") - for k,v in pairs(tags) do - if (myform) and (myform[v]) and (myform[v]["value"]) then - local val = myform[v] - if (val.type) and not (val.type == "hidden") then - io.write("\n\t<DT") - if (#val.errtxt > 0) then - val.class = "error" - io.write(" class='error'") - end - io.write(">" .. val.label .. "</DT>") - io.write("\n\t\t<DD>") - if (viewtype == "viewonly") then - io.write(val.value) - elseif (viewtype == "roles") then - for k,v in pairs(form.config.availableroles.option) do - local checked = "" - if (type(form.config.roles.option) == "table") then - for kk,vv in pairs(form.config.roles.option) do - if (v == vv) then - checked = "checked='yes'" - break - end - end - end - io.write("\n\t\t\t" ..v .. ":<input class='checkbox' type='checkbox' name='"..v.."' value='"..v.."' " .. checked .. " > ") - end - else - io.write(html.form[val.type](val)) - end - if (val.descr) and (#val.descr > 0) then io.write("\t\t<P CLASS='descr'>" .. string.gsub(val.descr, "\n", "<BR>") .. "</P>\n") end - if (#val.errtxt > 0) then io.write("\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>") end - io.write("\n\t\t</DD>") - else - io.write(html.form[val.type](val)) - end - end - end - io.write("\n</DL>") -end -?> - -<H1>CONFIG</H1> -<H2>Settings</H2> -<form name="settings" action="save" method="POST"> -<? -local myform = form.config -displayinfo(myform,{ "userid","orguserid", "username" }) -displayinfo(myform,{ "roles" },"roles") -displayinfo(myform,{ "password","password_confirm" }) -?> -<H2>Actions</H2> +<H1><?= form.label ?></H1> <? -local myform = form.config -local tags = { "cmdsave", "cmddelete", } -displayinfo(myform,tags) + form.action = "" + form.submit = "Save" + if form.value.password and form.value.password_confirm then + form.value.password.type = "password" + form.value.password_confirm.type = "password" + end + -- If not in newuser action, disable userid + if nil == string.find(ENV["PATH_INFO"], "/newuser") then + form.value.userid.contenteditable = false + end + local order = { "userid", "username", "roles", "password", "password_confirm" } + displayform(form, order) ?> -</form> <? --[[ DEBUG INFORMATION diff --git a/app/acf-util/password-status-html.lsp b/app/acf-util/password-status-html.lsp index e6d15b0..b7c9b05 100755 --- a/app/acf-util/password-status-html.lsp +++ b/app/acf-util/password-status-html.lsp @@ -7,77 +7,35 @@ io.write("</span>") --]] ?> -<? -function displayinfo(myform,tags,viewonly) - io.write("<DL>") - for k,v in pairs(tags) do - if (myform[v]) and (myform[v]["value"]) then - local val = myform[v] - io.write("\t<DT") - if (#val.errtxt > 0) then - val.class = "error" - io.write(" class='error'") - end - io.write(">" .. val.label .. "</DT>\n") - if (viewonly) then - io.write("\t\t<DD>" .. val.value .. "\n") - else - io.write("\t\t<DD>" .. html.form[val.type](val) .. "\n") - end - if (val.descr) and (#val.descr > 0) then io.write("\t\t<P CLASS='descr'>" .. string.gsub(val.descr, "\n", "<BR>") .. "</P>\n") end - if (#val.errtxt > 0) then io.write("\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>\n") end - io.write("\t\t</DD>\n") - end - end - io.write("</DL>") -end -?> - <H1>USER ACCOUNTS</H1> <H2>Create new account</H2> -<form name="createnew" action="" method="POST"> -<? -local myform = form.status -local tags = { "cmdnew", } -displayinfo(myform,tags) -?> +<form action="newuser" method="POST"> +<dl><dt><input class="submit" type="submit" value="New User"></dt></dl> </form> <H2>Existing account</H2> -<? ---function displayinfo(myform,tags,viewonly) -local myform = form.status.users - -io.write("<DL>") -if (type(myform) == "table") then - for k,v in pairs(myform) do - local myform = myform[k] - io.write("\t<DT") - if (#myform.errtxt > 0) then - myform.class = "error" - io.write(" class='error'") - end - io.write("><IMG SRC='/static/tango/16x16/apps/system-users.png' HEIGHT='16' WIDTH='16'> " .. myform.label .. "</DT>\n") - io.write("\t\t<DD>\n\t\t<TABLE>") - io.write("\n\t\t\t<TR>\n\t\t\t\t<TD><B>".. myform.value.userid.label .. - "</B></TD>\n\t\t\t\t<TD WIDTH='90%'>" .. myform.value.userid.value .. "</TD>\n\t\t\t</TR>") - io.write("\n\t\t\t<TR>\n\t\t\t\t<TD><B>".. myform.value.username.label .. - "</B></TD>\n\t\t\t\t<TD>" .. myform.value.username.value .. "</TD>\n\t\t\t</TR>") - io.write("\n\t\t\t<TR>\n\t\t\t\t<TD><B>".. myform.value.roles.label .. - "</B></TD>\n\t\t\t\t<TD>" .. myform.value.roles.value .. "</TD>\n\t\t\t</TR>") - if (myform.value.errors) then - io.write("\n\t\t\t<TR>\n\t\t\t\t<TD CLASS='error'><B>".. myform.value.errors.label .. - "</B></TD>\n\t\t\t\t<TD CLASS='error'>" .. myform.value.errors.value .. "</TD>\n\t\t\t</TR>") - end - io.write("</TD>\n\t\t\t</TR>") - io.write("\n\t\t\t<TR>\n\t\t\t\t<TD><B>Option</B></TD>\n\t\t\t\t<TD>[<A HREF='administrator?orguserid=".. myform.value.userid.value .. "'>Edit this account</A>]</TD>\n\t\t\t</TR>") - io.write("\n\t\t</TABLE>\n") - if (#myform.errtxt > 0) then io.write("\t\t<P CLASS='error'>" .. string.gsub(myform.errtxt, "\n", "<BR>") .. "</P>\n") end - io.write("\t\t</DD>\n") - end -end -io.write("</DL>") -?> - +<DL> +<? for name,user in pairs(form.value) do ?> + <DT><IMG SRC='/static/tango/16x16/apps/system-users.png' HEIGHT='16' WIDTH='16'> <?= name ?></DT> + <DD><TABLE> + <TR> + <TD><B><?= user.value.userid.label ?></B></TD> + <TD WIDTH='90%'><?= user.value.userid.value ?></TD> + </TR><TR> + <TD><B><?= user.value.username.label ?></B></TD> + <TD><?= user.value.username.value ?></TD> + </TR><TR> + <TD><B><?= user.value.roles.label ?></B></TD> + <TD><?= table.concat(user.value.roles.value, " / ") ?></TD> + </TR><TR> + <TD><B>Option</B></TD> + <TD> + [<A HREF='edituser?userid=<?= name ?>'>Edit this account</A>] + [<A HREF='deleteuser?userid=<?= name ?>'>Delete this account</A>] + </TD> + </TR> + </TABLE></DD> +<? end ?> +</DL> <? --[[ DEBUG INFORMATION diff --git a/app/acf_cli-controller.lua b/app/acf_cli-controller.lua index 2287067..7bd283d 100644 --- a/app/acf_cli-controller.lua +++ b/app/acf_cli-controller.lua @@ -39,14 +39,12 @@ exception_handler = function (self, message ) end -- create a Configuration Framework Entity (cfe) --- returns a table with at least "value", "type", "option" and "errtxt" +-- returns a table with at least "value", "type", and "label" cfe = function ( optiontable ) optiontable = optiontable or {} me = { value="", type="text", - option="", - errtxt="", - name="" } + label="" } for key,value in pairs(optiontable) do me[key] = value end diff --git a/app/acf_www-controller.lua b/app/acf_www-controller.lua index 9983293..98b732f 100644 --- a/app/acf_www-controller.lua +++ b/app/acf_www-controller.lua @@ -275,15 +275,12 @@ exception_handler = function (self, message ) end end --- create a Configuration Framework Entity (cfe) --- returns a table with at least "value", "type", "option" and "errtxt" +-- create a Configuration Framework Entity (cfe) +-- returns a table with at least "value", "type", and "label" cfe = function ( optiontable ) optiontable = optiontable or {} me = { value="", type="text", - option="", - errtxt="", - name="", label="" } for key,value in pairs(optiontable) do me[key] = value diff --git a/lib/authenticator-plaintext.lua b/lib/authenticator-plaintext.lua index 4c9bf08..b8cf598 100644 --- a/lib/authenticator-plaintext.lua +++ b/lib/authenticator-plaintext.lua @@ -47,12 +47,14 @@ pvt.parse_authfile = function(filename) end pvt.get_id = function(userid, authstruct) - if authstruct == nil then return nil end - for x = 1,#authstruct do - if authstruct[x].userid == userid then - return authstruct[x] + if authstruct ~= nil then + for x = 1,#authstruct do + if authstruct[x].userid == userid then + return authstruct[x] + end end end + return nil end --- public methods @@ -111,6 +113,42 @@ pvt.availablefields = function (field) } return availablefileds[field] end + +-- validate the settings (ignore password if it's nil) +local validate_settings = function (self, userid, username, password, password_confirm, roles) + local errormessage = {} + + -- Set errormessages when entering invalid values + if (#userid == 0) then errormessage.userid = "You need to enter a valid userid!" end + if password then + if (#password == 0) then + errormessage.password = "Password cannot be blank!" + elseif (password ~= password_confirm) then + errormessage.password_confirm = "You entered wrong password/confirmation" + else + local weak_password_result, weak_password_errormessage = pvt.weak_password(password) + if (weak_password_result) then errormessage.password = weak_password_errormessage end + end + end + local reverseroles = {} + for x,role in pairs(list_roles(self)) do + reverseroles[role] = x + end + for x,role in pairs(roles) do + if reverseroles[role] == nil then + errormessage.roles = "Invalid role" + break + end + end + + -- Return false if any errormessages are set + for k,v in pairs(errormessage) do + return false, errormessage + end + + return true, errormessage +end + -- This function returns the username and roles -- or false on an error get_userinfo = function ( self, userid ) @@ -150,7 +188,7 @@ list_roles = function (self) return output end -change_settings = function (self, userid,parameter,value) +change_settings = function (self, userid, parameter, value) local errormessage = {} local passwd_path = self.conf.confdir .. "/passwd" @@ -212,60 +250,102 @@ change_settings = function (self, userid,parameter,value) return true end -new_settings = function ( self, userid, username, password, password_confirm, roles) +-- For an existing user, change the settings that are non-nil +change_settings = function (self, userid, username, password, password_confirm, roles) + local result = true local errormessage = {} - -- We start by checking if user is allowed to do changes - if not (pvt.permission_to_change) then - errormessage.permissions = "No permission to change!" + + -- Get the current user info + local userinfo = get_userinfo(self, userid) + if userinfo == nil then + errormessage.userid = "This userid does not exist!" + result = false end - -- Set path to passwordfile - local passwd_path = self.conf.confdir .. "/passwd" + local change = username or password or password_confirm or roles + if change then + -- Validate the inputs + if (result == true) then + -- Use the current settings if new ones are nil, except for password + result, errormessage = validate_settings(self, userid, username or userinfo.username, password, password_confirm, roles or userinfo.roles) + end + + -- Update all the fields + if (result == true) then + userinfo.username = username or userinfo.username + if password then + userinfo.password = fs.md5sum_string(password) + end + userinfo.roles = roles or userinfo.roles + + -- write the updated user + delete_user(self, userid) + + -- Set path to passwordfile + local passwd_path = self.conf.confdir .. "/passwd" + -- Write the newline into the file + fs.write_line_file(passwd_path, userid .. ":" .. userinfo.password .. ":" .. userinfo.username .. ":" .. table.concat(userinfo.roles,",") ) + end + end + + return result, errormessage +end + +new_settings = function (self, userid, username, password, password_confirm, roles) + local result = true + local errormessage = {} + -- make sure to check all fields + userid = userid or "" + username = username or "" + password = password or "" + password_confirm = password_confirm or "" + roles = roles or {} - -- Set errormessages when entering invalid values - if (#userid == 0) then errormessage.userid = "You need to enter a valid userid!" end - if (password ~= password_confirm) then errormessage.password_confirm = "You entered wrong password/confirmation" end - if not (password) or (#password == 0) then errormessage.password = "Password cant be blank!" end --- if not (roles) or (#roles == 0) then errormessage.roles = "You need to enter some roles!" end - local weak_password_result, weak_password_errormessage = pvt.weak_password(password) - if (weak_password_result) then errormessage.password = weak_password_errormessage end -- Check if userid already used for k,v in pairs(list_users(self)) do if (v == userid) then errormessage.userid = "This userid already exists!" + result = false end end - -- Return false if some errormessages is set - for k,v in pairs(errormessage) do - return false, errormessage + -- validate the settings + if (result == true) then + result, errormessage = validate_settings(self, userid, username, password, password_confirm, roles) end - -- Write the newline into the file - fs.write_line_file(passwd_path, userid .. ":" .. fs.md5sum_string(password) .. ":" .. username .. ":" .. table.concat(roles,",") ) + -- write the new user + if (result == true) then + -- Set path to passwordfile + local passwd_path = self.conf.confdir .. "/passwd" - return true, errormessage + -- Write the newline into the file + fs.write_line_file(passwd_path, userid .. ":" .. fs.md5sum_string(password) .. ":" .. username .. ":" .. table.concat(roles,",") ) + end + + return result, errormessage end -delete_user = function( self, userid) - local errormessage = {} - local passwd_path = self.conf.confdir .. "/passwd" - - -- We start by checking if user is allowed to do changes - if not (pvt.permission_to_change) then - errormessage.permissions = "No permission to change!" - end +delete_user = function (self, userid) + local result = false + local errormessage = {userid="User not found"} + local passwd_path = self.conf.confdir .. "/passwd" local passwdfilecontent = fs.read_file_as_array(passwd_path) local output = {} for k,v in pairs(passwdfilecontent) do if not ( string.match(v, "^".. userid .. ":") ) then table.insert(output, v) + else + result = true + errormessage = {} end end --Save the updated table - fs.write_file(passwd_path, table.concat(output,"\n")) + if result == true then + fs.write_file(passwd_path, table.concat(output,"\n")) + end - return true, errormessage + return result, errormessage end diff --git a/lib/html.lua b/lib/html.lua index 136ce2b..0a23184 100644 --- a/lib/html.lua +++ b/lib/html.lua @@ -92,7 +92,7 @@ local generic_input = function ( field_type, v ) for i,k in ipairs ( { "name", "size", "checked", "maxlength", "value", "length", "class", "id", "src", - "align", "alt", + "align", "alt", "contenteditable", "tabindex", "accesskey", "onfocus", "onblur" } ) do str = str .. nv_pair ( k, v[k] ) @@ -129,7 +129,7 @@ form.longtext = function ( v ) end -function form.passwd ( v ) +function form.password ( v ) return generic_input ( "password", v ) end @@ -156,7 +156,7 @@ function form.image ( v ) end --- v.value is the selected item +-- v.value is the selected item (or an array if multiple) -- v.option is an array of valid options -- NOTE use of value and values (plural) function form.select ( v ) @@ -177,6 +177,12 @@ function form.select ( v ) end str = str .. ">" -- now the options + local reverseval = {} + if type(v.value) == "table" then + for x,val in ipairs(v.value) do + reverseval[val]=x + end + end for i, k in ipairs ( v.option ) do local val = k local txt = nil @@ -184,9 +190,13 @@ function form.select ( v ) txt=val[1] val=val[0] end - str = str .. "<option " - if ( v.value == val ) then - str = str .. " selected " + str = str .. "<option " + if type(v.value) == "table" then + if reverseval[val] then + str = str .. " selected" + end + elseif ( v.value == val ) then + str = str .. " selected" end str = str .. nv_pair("value", val) .. ">" .. k .. "</option>" end diff --git a/lib/viewfunctions.lua b/lib/viewfunctions.lua index d69f2cc..c7aa53f 100644 --- a/lib/viewfunctions.lua +++ b/lib/viewfunctions.lua @@ -4,14 +4,14 @@ function displayinfo(myform,tags,viewtype) if (myform[v]) and (myform[v]["value"]) then local val = myform[v] io.write("\n\t<DT") - if (#val.errtxt > 0) then + if (val.errtxt) then val.class = "error" io.write(" class='error'") end io.write(">" .. val.label .. "</DT>") io.write("\n\t\t<DD>") if (viewtype == "viewonly") then - if (val.value == "") and (val.errtxt == "") and ((val.descr) and (val.descr == "")) then val.value = " " end + if (val.value == "") and (val.errtxt == nil) and ((val.descr) and (val.descr == "")) then val.value = " " end io.write(val.value) elseif (val.type == "radio") and (type(val.option) == "table") and (#val.option > 0) then io.write("<span style='display:inline' class='" .. ( val.class or "") .. "'>") @@ -26,7 +26,7 @@ function displayinfo(myform,tags,viewtype) io.write(html.form[val.type](val)) end if (val.descr) and (#val.descr > 0) then io.write("\n\t\t<P CLASS='descr'>" .. string.gsub(val.descr, "\n", "<BR>") .. "</P>") end - if (#val.errtxt > 0) then io.write("\n\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>") end + if (val.errtxt) then io.write("\n\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>") end io.write("\n\t\t</DD>\n") end end @@ -46,31 +46,94 @@ function displaymanagement (myform,tags) end if (myform) and (myform[tags[1]]) then - io.write('<dt>' .. (myform[tags[1]]["label"] or myform[tags[1]]["name"]) .. '</dt>') - io.write('<dd>') - --Show buttons - for k,v in pairs(tags) do - if (myform[v]) then - io.write(html.form[myform[v].type](myform[v])) + io.write('<dt>' .. (myform[tags[1]]["label"] or myform[tags[1]]["name"]) .. '</dt>') + io.write('<dd>') + --Show buttons + for k,v in pairs(tags) do + if (myform[v]) then + io.write(html.form[myform[v].type](myform[v])) + end + end + if (descriptions) and (#descriptions > 0) then + io.write("\n\t\t<P CLASS='descr'>" .. string.gsub(descriptions, "\n", "<BR>") .. "</P>") + end + if (errors) and (#errors > 0) then + io.write("\n\t\t<P CLASS='error'>" .. string.gsub(errors, "\n", "<BR>") .. "</P>") end + io.write('</dd>') + + -- Display the result of previous action + if (myform) and (myform['actionresult']) then + if (myform['actionresult']['errtxt']) and (#myform['actionresult']['errtxt'] > 0) then + io.write('<dt class="error">' .. myform['actionresult']['label'] .. '</dt>') + io.write('<dd><pre class="error">' .. (myform['actionresult']['errtxt'] or "") .. '</pre></dd>') + elseif (myform['actionresult']['descr']) and (#myform['actionresult']['descr'] > 0) then + io.write('<dt>' .. myform['actionresult']['label'] .. '</dt>') + io.write('<dd><pre>' .. (myform['actionresult']['descr'] or "") .. '</pre></dd>') + end + end + end +end + +function displayitem(myitem, viewtype) + io.write("<DT") + if myitem.errtxt then + myitem.class = "error" + io.write(" class='error'") end - if (descriptions) and (#descriptions > 0) then - io.write("\n\t\t<P CLASS='descr'>" .. string.gsub(descriptions, "\n", "<BR>") .. "</P>") + io.write(">" .. myitem.label .. "</DT>\n") + io.write("<DD>") + if (viewtype == "viewonly") then + myitem.disabled = "true" end - if (errors) and (#errors > 0) then - io.write("\n\t\t<P CLASS='error'>" .. string.gsub(errors, "\n", "<BR>") .. "</P>") + if myitem.type == "multi" then + -- FIXME multiple select doesn't work in haserl, so use series of checkboxes + --myitem.type = "select" + --myitem.multiple = "true" + local tempname = myitem.name + local tempval = myitem.value + local reverseval = {} + for x,val in ipairs(tempval) do + reverseval[val] = x + end + for x,val in ipairs(myitem.option) do + myitem.value = val + myitem.checked = reverseval[val] + myitem.name = tempname .. "." .. val + io.write(html.form.checkbox(myitem) .. val .. "<br>\n") + end + myitem.name = tempname + myitem.value = tempval + else + io.write(html.form[myitem.type](myitem) .. "\n") end - io.write('</dd>') + if myitem.descr then io.write("<P CLASS='descr'>" .. string.gsub(myitem.descr, "\n", "<BR>") .. "</P>\n") end + if myitem.errtxt then io.write("<P CLASS='error'>" .. string.gsub(myitem.errtxt, "\n", "<BR>") .. "</P>\n") end + io.write("</DD>\n") +end - -- Display the result of previous action - if (myform) and (myform['actionresult']) then - if (myform['actionresult']['errtxt']) and (#myform['actionresult']['errtxt'] > 0) then - io.write('<dt class="error">' .. myform['actionresult']['label'] .. '</dt>') - io.write('<dd><pre class="error">' .. (myform['actionresult']['errtxt'] or "") .. '</pre></dd>') - elseif (myform['actionresult']['descr']) and (#myform['actionresult']['descr'] > 0) then - io.write('<dt>' .. myform['actionresult']['label'] .. '</dt>') - io.write('<dd><pre>' .. (myform['actionresult']['descr'] or "") .. '</pre></dd>') +function displayform(myform, order) + if myform.descr then io.write("<P CLASS='descr'>" .. string.gsub(myform.descr, "\n", "<BR>") .. "</P>\n") end + if myform.errtxt then io.write("<P CLASS='error'>" .. string.gsub(myform.errtxt, "\n", "<BR>") .. "</P>\n") end + io.write('<form action="' .. myform.action .. '" method="POST">\n') + io.write('<DL>\n') + local reverseorder= {} + if order then + for x,name in ipairs(order) do + reverseorder[name] = x + if myform.value[name] then + myform.value[name].name = name + displayitem(myform.value[name]) + end end end -end + for name,item in pairs(myform.value) do + if nil == reverseorder[name] then + item.name = name + displayitem(item) + end + end + io.write('<DT><input class="submit" type="submit" value="' .. myform.submit .. '"></DT>\n') + io.write('</DL>\n') + io.write('</FORM>') end @@ -1,4 +1,4 @@ ALL=welcome:read,logon:logon,logon:logout,logon:status -CREATE=password:administrator,password:status -READ=password:editme,password:save +CREATE=password:status,password:edituser,password:newuser,password:deleteuser +READ=password:editme NONE=roles:read,roles:getlist |