diff --git a/modules/webaccess/lib/access_control_variables.py.wml b/modules/webaccess/lib/access_control_variables.py.wml new file mode 100644 index 000000000..614b1224a --- /dev/null +++ b/modules/webaccess/lib/access_control_variables.py.wml @@ -0,0 +1,38 @@ +## $Id$ +## CDSware Access Control Variables in mod_python. + +## This file is part of the CERN Document Server Software (CDSware). +## Copyright (C) 2002 CERN. +## +## The CDSware is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2 of the +## License, or (at your option) any later version. +## +## The CDSware is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with CDSware; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +"""CDSware Access Control Variables. """ + +<protect> ## okay, rest of the Python code goes below ####### + +__version__ = "$Id$" + +# VALUES TO BE EXPORTED +# CURRENTLY USED BY THE FILES access_control_engine.py access_control_admin.py webaccessadmin_lib.py + +# name of the role giving superadmin rights +SUPERADMINROLE = 'superadmin' +# name of the action allowing roles to access the web administrator interface +WEBACCESSACTION = 'accesswebadmin' +# name of the action allowing roles to delegate the rights to other roles +# ex: libraryadmin to delegate libraryworker +DELEGATEADDUSERROLE = 'delegate_adduserrole' + +</protect> diff --git a/modules/webaccess/lib/webaccessadmin_lib.py b/modules/webaccess/lib/webaccessadmin_lib.py new file mode 100644 index 000000000..723c49136 --- /dev/null +++ b/modules/webaccess/lib/webaccessadmin_lib.py @@ -0,0 +1,2537 @@ +## $Id$ +## Administrator interface for WebAccess + +## This file is part of the CERN Document Server Software (CDSware). +## Copyright (C) 2002 CERN. +## +## The CDSware is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2 of the +## License, or (at your option) any later version. +## +## The CDSware is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with CDSware; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +## read config variables: +#include "config.wml" +#include "configbis.wml" + +<protect>## $Id$</protect> +<protect>## DO NOT EDIT THIS FILE! IT WAS AUTOMATICALLY GENERATED FROM CDSware WML SOURCES.</protect> +"""CDSware WebAccess Administrator Interface.""" + +__lastupdated__ = """<: print `date +"%d %b %Y %H:%M:%S %Z"`; :>""" + +## fill config variables: +pylibdir = "<LIBDIR>/python" + +try: + import sys + sys.path.append('%s' % pylibdir) + import cdsware.access_control_engine as acce + import cdsware.access_control_admin as acca + reload(acce) + reload(acca) + import cgi + import re + + from cdsware.dbquery import run_sql + from cdsware.access_control_variables import SUPERADMINROLE, WEBACCESSACTION, DELEGATEADDUSERROLE + from cdsware.config import * + from cdsware.webpage import page, pageheaderonly, pagefooteronly + from cdsware.webuser import getUid, get_email + from mod_python import apache +except ImportError, e: + print "Error: %s" % e + import sys + sys.exit(1) + +__version__ = "$Id$" + + +def index(req, title='', body='', subtitle='', authorized=0): + """main function to show pages for webaccessadmin. + + 1. if user not logged in and administrator, show the mustlogin page + + 2. if used without body argument, show the startpage + + 3. show admin page with title, body, subtitle and navtrail. + + authorized - if 1, don't check if the user is allowed to be webadmin """ + + # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> > + # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> > + # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin</a> > """ + navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> > <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> """ + + if body and not authorized: navtrail_previous_links += '> <a class=navtrail href=<WEBURL>/admin/webaccess/webaccessadmin.py>Manage WebAccess</a>' + + id_user = getUid(req) + + if not authorized and not is_adminuser(req): return mustloginpage(req) + + elif not body: + title = 'Manage WebAccess' + body = startpage() + elif type(body) != str: body = addadminbox(subtitle, datalist=body) + + return page(title=title, + uid=id_user, + body=body, + navtrail=navtrail_previous_links, + lastupdated=__lastupdated__) + + +def mustloginpage(req): + """show a page asking the user to login.""" + + # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> > + # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> > + # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin Area</a>""" + navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> > <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> > """ + + return page(title='Authorization failure', + uid=getUid(req), + body=adderrorbox('try to login first', + datalist=["""You are not a user authorized to perform admin tasks, try to + <a href="http://cdsdev.cern.ch:8000/DEMODEV/youraccount.py/login">login</a>."""]), + navtrail=navtrail_previous_links, + lastupdated=__lastupdated__) + + +def is_adminuser(req): + """check if user is a registered administrator. """ + + id_user = getUid(req) + return acce.acc_authorize_action(id_user, WEBACCESSACTION) + + +def perform_rolearea(req): + """create the role area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + header = ['id', 'name', 'description', 'users', 'authorizations / actions', 'role', ''] + roles = acca.acc_getAllRoles() + + roles2 = [] + for (id, name, desc) in roles: + if len(desc) > 30: desc = desc[:30] + '...' + roles2.append([id, name, desc]) + for col in [(('add', 'adduserrole'), + ('remove', 'deleteuserrole')), + (('add', 'addauthorization'), + ('modify', 'modifyauthorizations'), + ('remove', 'deleteroleaction')), + (('delete', 'deleterole'), ), + (('show details', 'showroledetails'), )]: + roles2[-1].append('<a href="%s?id_role=%s">%s</a>' % (col[0][1], id, col[0][0])) + for (str, function) in col[1:]: + roles2[-1][-1] += ' / <a href="%s?id_role=%s">%s</a>' % (function, id, str) + + output = """ + <dl> + <dt>Users:</dt> + <dd>add or remove users from the access to a role and its priviliges.</dd> + <dt>Authorizations/Actions:</dt> + <dd>these terms means almost the same, but an authorization is a <br> + connection between a role and an action (possibly) containing arguments.</dd> + <dt>Roles:</dt> + <dd>see all the information attached to a role and decide if you want to<br>delete it.</dd> + </dl> + """ + + output += tupletotable(header=header, tuple=roles2) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + return index(req=req, + title='Role Administration', + subtitle='administration with roles as access point', + body=[output, extra]) + + +def perform_actionarea(req): + """create the action area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + header = ['id', 'name', 'authorizations/roles', 'action', ''] + actions = acca.acc_getAllActions() + + actions2 = [] + roles2 = [] + for (id, name, dontcare) in actions: + actions2.append([id, name]) + for col in [(('add', 'addauthorization'), + ('modify', 'modifyauthorizations'), + ('remove', 'deleteroleaction')), + (('delete', 'deleteaction'), ), + (('show details', 'showactiondetails'), )]: + actions2[-1].append('<a href="%s?id_action=%s&reverse=1">%s</a>' % (col[0][1], id, col[0][0])) + for (str, function) in col[1:]: + actions2[-1][-1] += ' / <a href="%s?id_action=%s&reverse=1">%s</a>' % (function, id, str) + + output = """ + <dl> + <dt>Authorizations/Roles:</dt> + <dd>these terms means almost the same, but an authorization is a <br> + connection between a role and an action (possibly) containing arguments.</dd> + <dt>Actions:</dt> + <dd>see all the information attached to an action and decide if you want to<br>delete it.</dd> + </dl> + """ + + output += tupletotable(header=header, tuple=actions2) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a> + <dd>go here to add a new role. + <dt><a href="addaction">Add new action</a> + <dd>go here to add a new action. + </dl> + """ + + return index(req=req, + title='Action Administration', + subtitle='administration with actions as access point', + body=[output, extra]) + + +def perform_userarea(req, email_user_pattern=''): + """create area to show info about users. """ + + if not is_adminuser(req): return mustloginpage(req) + + subtitle = 'step 1 - search for users' + + output = """ + <p> + search for users to display. + </p> """ + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">1. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="userarea", + text=text, + button="search for users") + + if email_user_pattern: + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id LIMIT 26""" % (email_user_pattern, )) + + if not users1: + output += '<p>no matching users</p>' + else: + subtitle = 'step 2 - select what to do with user' + + users = [] + for (id, email) in users1[:25]: + users.append([id, email]) + for col in [(('add', 'addroleuser'), + ('remove', 'deleteuserrole')), + (('show details', 'showuserdetails'), )]: + users[-1].append('<a href="%s?email_user_pattern=%s&id_user=%s">%s</a>' % (col[0][1], email_user_pattern, id, col[0][0])) + for (str, function) in col[1:]: + users[-1][-1] += ' / <a href="%s?email_user_pattern=%s&id_user=%s&reverse=1">%s</a>' % (function, email_user_pattern, id, str) + + output += '<p>found <strong>%s</strong> matching users</p>' % (len(users1), ) + output += tupletotable(header=['id', 'email', 'roles', ''], tuple=users) + + if len(users1) > 25: + output += '<p><strong>only showing the first 25 users, narrow your search...</strong></p>' + + return index(req=req, + title='User Administration', + subtitle=subtitle, + body=[output]) + + +def perform_resetarea(req): + """create the reset area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + output = """ + <dl> + <dt><a href="resetdefaultsettings">Reset to Default Authorizations</a> + <dd>Remove all changes that has been done to the roles and <br> + add only the default authorization settings. + <dt><a href="adddefaultsettings">Add Default Authorizations</a> + <dd>Keep all changes and add the default authorization settings. + </dl> + """ + + return index(req=req, + title='Reset Authorizations', + subtitle='reseting to or adding default authorizations', + body=[output]) + + +def perform_resetdefaultsettings(req, superusers=[], confirm=0): + """delete all roles, actions and authorizations presently in the database + and add only the default roles. + only selected users will be added to superadmin, rest is blank """ + + if not is_adminuser(req): return mustloginpage(req) + + # cleaning input + if type(superusers) == str: superusers = [superusers] + + # remove not valid e-mails + for email in superusers: + if not check_email(email): superusers.remove(email) + + # instructions + output = """ + <p> + before you reset the settings, we need some users<br> + to connect to <strong>%s</strong>.<br> + enter as many e-mail adresses you want and press <strong>reset</strong>.<br> + <strong>confirm reset settings</strong> when you have added enough e-mails.<br> + <strong><SUPPORTEMAIL></strong> is added as default. + </p>""" % (SUPERADMINROLE, ) + + # add more superusers + output += """ + <p>enter user e-mail addresses: </p> + <form action="resetdefaultsettings" method="POST">""" + + for email in superusers: + output += ' <input type="hidden" name="superusers" value="%s" />' % (email, ) + + output += """ + <span class="adminlabel">e-mail</span> + <input class="admin_wvar" type="text" name="superusers" /> + <input class="adminbutton" type="submit" value="add e-mail" /> + </form>""" + + + if superusers: + # remove emails + output += """ + <form action="resetdefaultsettings" method="POST"> + have you entered wrong data? + <input class="adminbutton" type="submit" value="remove all e-mails" /> + </form> + """ + + # superusers confirm table + start = '<form action="resetdefaultsettings" method="POST">' + + extra = ' <input type="hidden" name="confirm" value="1" />' + for email in superusers: + extra += '<input type="hidden" name="superusers" value="%s" />' % (email, ) + extra += ' <input class="adminbutton" type="submit" value="confirm to reset settings" />' + + end = '</form>' + + output += '<p><strong>reset default settings</strong> with the users below? </p>' + output += tupletotable(header=['e-mail address'], + tuple=superusers, + start=start, + extracolumn=extra, + end=end) + + if confirm in [1, "1"]: + res = acca.acc_reset_default_settings(superusers) + if res: + output += '<p>successfully reset default settings</p>' + else: + output += '<p>sorry, could not reset default settings</p>' + + return index(req=req, + title='Reset Default Settings', + subtitle='reset settings', + body=[output]) + + +def perform_adddefaultsettings(req, superusers=[], confirm=0): + """add the default settings, and keep everything else. + probably nothing will be deleted, except if there has been made changes to the defaults.""" + + if not is_adminuser(req): return mustloginpage(req) + + # cleaning input + if type(superusers) == str: superusers = [superusers] + + # remove not valid e-mails + for email in superusers: + if not check_email(email): superusers.remove(email) + + # instructions + output = """ + <p> + before you add the settings, we need some users<br> + to connect to <strong>%s</strong>.<br> + enter as many e-mail adresses you want and press <strong>add</strong>.<br> + <strong>confirm add settings</strong> when you have added enough e-mails.<br> + <strong><SUPPORTEMAIL></strong> is added as default. + </p>""" % (SUPERADMINROLE, ) + + # add more superusers + output += """ + <p>enter user e-mail addresses: </p> + <form action="adddefaultsettings" method="POST">""" + + for email in superusers: + output += ' <input type="hidden" name="superusers" value="%s" />' % (email, ) + + output += """ + <span class="adminlabel">e-mail</span> + <input class="admin_wvar" type="text" name="superusers" /> + <input class="adminbutton" type="submit" value="add e-mail" /> + </form> + """ + + if superusers: + # remove emails + output += """ + <form action="adddefaultsettings" method="POST"> + have you entered wrong data? + <input class="adminbutton" type="submit" value="remove all e-mails" /> + </form> + """ + + # superusers confirm table + start = '<form action="adddefaultsettings" method="POST">' + + extra = ' <input type="hidden" name="confirm" value="1" />' + for email in superusers: + extra += '<input type="hidden" name="superusers" value="%s" />' % (email, ) + extra += ' <input class="adminbutton" type="submit" value="confirm to add settings" />' + + end = '</form>' + + output += '<p><strong>add default settings</strong> with the users below? </p>' + output += tupletotable(header=['e-mail address'], + tuple=superusers, + start=start, + extracolumn=extra, + end=end) + + if confirm in [1, "1"]: + res = acca.acc_add_default_settings(superusers) + if res: + output += '<p>successfully added default settings</p>' + else: + output += '<p>sorry, could not add default settings</p>' + + return index(req=req, + title='Add Default Settings', + subtitle='add settings', + body=[output]) + + +def perform_delegate_startarea(req): + """start area for lower level delegation of rights.""" + + subtitle = 'select what to do' + + output = '' + + if is_adminuser(req): + output += """ + <p> + You are also allowed to be in the <a href="../webaccessadmin.py">Main Admin Area</a> which gives you<br> + the access to the full functionality of WebAccess. + </p> + """ + + output += """ + <dl> + <dt><a href="delegate_adduserrole">Add users to roles</a> + <dd>add users to the roles you have delegation rights to. + <dt><a href="delegate_deleteuserrole">Remove users from roles</a> + <dd>remove users from the roles you have delegation rights to. + </dl> + """ + + return index(req=req, + title='Delegate Rights - start area', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_delegate_adduserrole(req, id_role=0, email_user_pattern='', id_user=0, confirm=0): + """let a lower level web admin add users to a limited set of roles. + + id_role - the role to connect to a user + + id_user - the user to connect to a role + + confirm - make the connection happen """ + + # finding the allowed roles for this user + id_admin = getUid(req) + id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) + actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action) + + allowed_roles = [] + for (id, arglistid, name_role_help) in actions[1:]: + id_role_help = acca.acc_getRoleId(name_role=name_role_help) + if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles: + allowed_roles.append([id_role_help, name_role_help, '']) + + output = '' + + if not allowed_roles: + subtitle = 'no delegation rights' + output += """ + <p> + You do not have the delegation rights over any roles.<br> + If you think you should have such rights, contact a WebAccess Administrator. + </p>""" + else: + subtitle = 'step 1 - select role' + + output += """ + <p> + Lower level delegation of access rights to roles.<br> + An administrator with all rights have to give you these rights. + </p>""" + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + output += createroleselect(id_role=id_role, step=1, name='id_role', + action='delegate_adduserrole', roles=allowed_roles) + + if str(id_role) != '0': + subtitle = 'step 2 - search for users' + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">2. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="delegate_adduserrole", + text=text, + button="search for users", + id_role=id_role) + + # pattern is entered + if email_user_pattern: + # users with matching email-address + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + # users that are connected + users2 = run_sql("""SELECT DISTINCT u.id, u.email + FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user + WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s' + ORDER BY u.id """ % (id_role, email_user_pattern)) + + # no users that match the pattern + if not (users1 or users2): + output += 'no qualified users, try new search' + # show matching users + else: + subtitle = 'step 3 - select a user' + + users = [] + extrausers = [] + for (id, email) in users1: + if (id, email) not in users2: users.append([id,email,'']) + for (id, email) in users2: + extrausers.append([-id, email,'']) + + output += createuserselect(id_user=id_user, + action="delegate_adduserrole", + step=3, + users=users, + extrausers=extrausers, + button="add this user", + id_role=id_role, + email_user_pattern=email_user_pattern) + + try: id_user = int(id_user) + except ValueError: pass + # user selected already connected to role + if id_user < 0: + output += '<p>users in brackets are already attached to the role, try another one</p>' + # a user is selected + elif email_out: + subtitle = "step 4 - confirm to add user" + + output += createhiddenform(action="delegate_adduserrole", + text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role), + id_role=id_role, + email_user_pattern=email_user_pattern, + id_user=id_user, + confirm=1) + + # it is confirmed that this user should be added + if confirm: + # add user + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm user added' + output += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role) + else: + subtitle = 'step 5 - user could not be added' + output += '<p>sorry, but user could not be added.</p>' + + return index(req=req, + title='Delegate Rights - add users to roles', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_delegate_deleteuserrole(req, id_role=0, id_user=0, confirm=0): + """let a lower level web admin remove users from a limited set of roles. + + id_role - the role to connect to a user + + id_user - the user to connect to a role + + confirm - make the connection happen """ + + subtitle = 'in progress...' + + output = '<p>in progress...</p>' + + # finding the allowed roles for this user + id_admin = getUid(req) + id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) + actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action) + + output = '' + + if not actions: + subtitle = 'no delegation rights' + output += """ + <p> + You do not have the delegation rights over any roles.<br> + If you think you should have such rights, contact a WebAccess Administrator. + </p>""" + else: + subtitle = 'step 1 - select role' + + output += """ + <p> + Lower level delegation of access rights to roles.<br> + An administrator with all rights have to give you these rights. + </p>""" + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + allowed_roles = [] + for (id, arglistid, name_role_help) in actions[1:]: + id_role_help = acca.acc_getRoleId(name_role=name_role_help) + if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles: + allowed_roles.append([id_role_help, name_role_help, '']) + + output += createroleselect(id_role=id_role, step=1, + action='delegate_deleteuserrole', roles=allowed_roles) + + if str(id_role) != '0': + subtitle = 'step 2 - select user' + + users = acca.acc_getRoleUsers(id_role) + + output += createuserselect(id_user=id_user, step=2, + action='delegate_deleteuserrole', users=users, + id_role=id_role) + + if str(id_user) != '0': + subtitle = 'step 3 - confirm delete of user' + email_user = acca.acc_getUserEmail(id_user=id_user) + + output += createhiddenform(action="delegate_deleteuserrole", + text='delete user %s from %s?' + % (headerstrong(user=id_user), headerstrong(role=id_role)), + id_role=id_role, + id_user=id_user, + confirm=1) + + if confirm: + res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role) + if res: + subtitle = 'step 4 - confirm user deleted from role' + output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role) + else: + subtitle = 'step 4 - user could not be deleted' + output += 'sorry, but user could not be deleted<br>user is probably already deleted.' + + return index(req=req, + title='Delegate Rights - remove users from roles', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_addaction(req, name_action='', arguments='', optional='no', description='put description here.', confirm=0): + """form to add a new action with these values: + + name_action - name of the new action + + arguments - allowedkeywords, separated by whitespace + + description - optional description of the action""" + + if not is_adminuser(req): return mustloginpage(req) + + name_action = cleanstring(name_action) + arguments = cleanstring(arguments, comma=1) + + title = 'Add Action' + subtitle = 'step 1 - give values to the requested fields' + + output = """ + <form action="addaction" method="POST"> + <span class="adminlabel">action name </span> + <input class="admin_wvar" type="text" name="name_action" value="%s" /> <br> + <span class="adminlabel">arguments </span> + <input class="admin_wvar" type="text" name="arguments" value="%s" /> + <small>keywords for arguments, separate with comma, no whitespace.</small> <br> + <span class="adminlabel">optional arguments</span> + <select name="optional" class="admin_w200"> + <option value="no" selected="selected">no, not allowed</option> + <option value="yes" %s>yes, allowed</option> + </select><br> + <span class="adminlabel">description </span> + <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> + <input class="adminbutton" type="submit" value="add action" /> + </form> + """ % (name_action, arguments, optional == 'yes' and 'selected="selected"' or '', description) + + if name_action: + # description must be changed before it is submitted + if description == 'put description here.': internaldesc = '' + else: internaldesc = description + + if arguments: + subtitle = 'step 2 - confirm to add action with %s arguments' % (optional == 'yes' and 'optional' or '', ) + arguments = arguments.replace(' ', '') + text = 'add action with: <br>\n' + text += 'name: <strong>%s</strong><br>\n' % (name_action, ) + if internaldesc: + text += 'description: <strong>%s</strong><br>\n' % (description, ) + text += '%sarguments: <strong>%s</strong><br>' % (optional == 'yes' and 'optional ' or '', arguments) + text += 'optional: <strong>%s</strong>?' % (optional, ) + + else: + optional = 'no' + subtitle = 'step 2 - confirm to add action without arguments' + text = 'add action <strong>%s</strong> without arguments' % (name_action, ) + if internaldesc: text += '<br>\nand description: <strong>%s</strong>?\n' % (description, ) + else: text += '?\n' + + output += createhiddenform(action="addaction", + text=text, + name_action=name_action, + arguments=arguments, + optional=optional, + description=description, + confirm=1) + + if confirm not in ["0", 0]: + arguments = arguments.split(',') + result = acca.acc_addAction(name_action, + internaldesc, + optional, + *arguments) + + if result: + subtitle = 'step 3 - action added' + output += '<p>action added:</p>' + output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords', 'optional'], + tuple=[result]) + else: + subtitle = 'step 3 - action could not be added' + output += '<p>sorry, could not add action, <br>action with the same name probably exists.</p>' + + extra = """ + <dl> + <dt><a href="addauthorization?id_action=%s&reverse=1">Add authorization</a></dt> + <dd>start adding new authorizations to this action.</dd> + </dl> """ % (acca.acc_getActionId(name_action=name_action, )) + + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title=title, + body=body, + subtitle=subtitle) + + +def perform_deleteaction(req, id_action="0", confirm=0): + """show all roles connected, and ask for confirmation. + + id_action - id of action to delete """ + + if not is_adminuser(req): return mustloginpage(req) + + title='Delete Action' + subtitle='step 1 - select action to delete' + name_action = acca.acc_getActionName(id_action=id_action) + + output = createactionselect(id_action=id_action, + action="deleteaction", + step=1, + actions=acca.acc_getAllActions(), + button="delete action") + + if id_action != "0": + subtitle = 'step 2 - confirm the delete' + + output += actiondetails(id_action=id_action) + + if acca.acc_getActionRoles(id_action=id_action): + output += createhiddenform(action="deleteroleaction", + text="""rather delete only connection between this action + and a selected role?""", + id_action=id_action, + reverse=1, + button='go there') + + output += createhiddenform(action="deleteaction", + text=' delete action <strong>%s</strong> and all connections?' % (name_action, ), + confirm=1, + id_action=id_action) + + if confirm: + subtitle = 'step 3 - confirm delete of action' + res = acca.acc_deleteAction(id_action=id_action) + if res: + output += '<p>confirm: action <strong>%s</strong> deleted.<br>\n' % (name_action, ) + output += '%s entries deleted all in all.</p>\n' % (res, ) + else: + output += '<p>sorry, action could not be deleted.</p>\n' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showactiondetails(req, id_action): + """show the details of an action. """ + + if not is_adminuser(req): return mustloginpage(req) + + if id_action not in [0, '0']: + output = actiondetails(id_action=id_action) + + extra = """ + <dl> + <dt><a href="addauthorization?id_action=%s&reverse=1">Add new authorization</a></dt> + <dd>add an authorization.</dd> + <dt><a href="modifyauthorizations?id_action=%s&reverse=1">Modify authorizations</a></dt> + <dd>modify existing authorizations.</dd> + </dl> + """ % (id_action, id_action) + body = [output, extra] + + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show Action Details', + subtitle='show action details', + body=body) + + +def actiondetails(id_action=0): + """show details of given action. """ + + output = '' + + if id_action not in [0, '0']: + name_action = acca.acc_getActionName(id_action=id_action) + + output += '<p>action details:</p>' + output += tupletotable(header=['id', 'name', 'description', 'allowedkeywords', 'optional'], + tuple=[acca.acc_getActionDetails(id_action=id_action)]) + + roleshlp = acca.acc_getActionRoles(id_action=id_action) + if roleshlp: + roles = [] + for (id, name, dontcare) in roleshlp: + roles.append([id, name, + '<a href="simpleauthorization?id_role=%s&id_action=%s">show authorization details</a>' + % (id, id_action), + '<a href="simpleroleusers?id_role=%s">show connected users</a>' % (id, )]) + roletable = tupletotable(header=['id', 'name', '', ''], tuple=roles) + + output += '<p>roles connected to %s:</p>\n' % (headerstrong(action=name_action, query=0), ) + output += roletable + + else: + output += '<p>no roles connected to %s.</p>\n' % (headerstrong(action=name_action, query=0), ) + + else: + output += '<p>no details to show</p>' + + return output + + +def perform_addrole(req, name_role='', description='put description here.', confirm=0): + """form to add a new role with these values: + + name_role - name of the new role + + description - optional description of the role """ + + if not is_adminuser(req): return mustloginpage(req) + + name_role = cleanstring(name_role) + + title='Add Role' + subtitle = 'step 1 - give values to the requested fields' + + output = """ + <form action="addrole" method="POST"> + <span class="adminlabel">role name </span> + <input class="admin_wvar" type="text" name="name_role" value="%s" /> <br> + <span class="adminlabel">description </span> + <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> + <input class="adminbutton" type="submit" value="add role" /> + </form> + """ % (name_role, description) + + if name_role: + # description must be changed before submitting + subtitle = 'step 2 - confirm to add role' + internaldesc = '' + if description != 'put description here.': + internaldesc = description + + text = """ + add role with: <br>\n + name: <strong>%s</strong> <br>""" % (name_role, ) + if internaldesc: + text += 'description: <strong>%s</strong>?\n' % (description, ) + + output += createhiddenform(action="addrole", + text=text, + name_role=name_role, + description=description, + confirm=1) + + if confirm not in ["0", 0]: + result = acca.acc_addRole(name_role=name_role, + description=internaldesc) + + if result: + subtitle = 'step 3 - role added' + output += '<p>role added: </p>' + output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords'], + tuple=[result]) + else: + subtitle = 'step 3 - role could not be added' + output += '<p>sorry, could not add role, <br>role with the same name probably exists.</p>' + + extra = """ + <dl> + <dt><a href="addauthorization?id_role=%s">Add authorization</a></dt> + <dd>start adding new authorizations to this role.</dd> + </dl> """ % (acca.acc_getRoleId(name_role=name_role), ) + + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title=title, + body=body, + subtitle=subtitle) + + +def perform_deleterole(req, id_role="0", confirm=0): + """select a role and show all connected information, + + users - users that can access the role. + + actions - actions with possible authorizations.""" + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Delete role' + subtitle = 'step 1 - select role to delete' + name_role = id_role + + name_role = acca.acc_getRoleName(id_role=id_role) + output = createroleselect(id_role=id_role, + action="deleterole", + step=1, + roles=acca.acc_getAllRoles(), + button="delete role") + + if id_role != "0": + subtitle = 'step 2 - confirm delete of role' + + output += roledetails(id_role=id_role) + + output += createhiddenform(action="deleterole", + text='delete role <strong>%s</strong> and all connections?' % (name_role, ), + id_role=id_role, + confirm=1) + + if confirm: + res = acca.acc_deleteRole(id_role=id_role) + subtitle = 'step 3 - confirm role deleted' + if res: + output += "<p>confirm: role <strong>%s</strong> deleted.<br>" % (name_role, ) + output += "<strong>%s</strong> entries were removed.</p>" % (res, ) + else: + output += "<p>sorry, the role could not be deleted.</p>" + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showroledetails(req, id_role): + """show the details of a role.""" + + if not is_adminuser(req): return mustloginpage(req) + + if id_role not in [0, '0']: + output = roledetails(id_role=id_role) + + extra = """ + <dl> + <dt><a href="adduserrole?id_role=%s">Connect user</a></dt> + <dd>connect a user to the role.</dd> + <dt><a href="addauthorization?id_role=%s">Add new authorization</a></dt> + <dd>add an authorization.</dd> + <dt><a href="modifyauthorizations?id_role=%s">Modify authorizations</a></dt> + <dd>modify existing authorizations.</dd> + </dl> + """ % (id_role, id_role, id_role) + body = [output, extra] + + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show Role Details', + subtitle='show role details', + body=body) + + +def roledetails(id_role=0): + """create the string to show details about a role. """ + + name_role = acca.acc_getRoleName(id_role=id_role) + + usershlp = acca.acc_getRoleUsers(id_role) + users = [] + for (id, email, dontcare) in usershlp: + users.append([id, email, '<a href="showuserdetails?id_user=%s">show user details</a>' % (id, )]) + usertable = tupletotable(header=['id', 'email'], tuple=users) + + actionshlp = acca.acc_getRoleActions(id_role) + actions = [] + for (id, name, dontcare) in actionshlp: + actions.append([id, name, + '<a href="showactiondetails?id_role=%s&id_action=%s">show action details</a>' % (id_role, id), + '<a href="simpleauthorization?id_role=%s&id_action=%s">show authorization details</a>' % (id_role, id)]) + + actiontable = tupletotable(header=['id', 'name', '', ''], tuple=actions) + + # show role details + details = '<p>role details:</p>' + details += tupletotable(header=['id', 'name', 'description'], + tuple=[acca.acc_getRoleDetails(id_role=id_role)]) + + # show connected users + details += '<p>users connected to %s:</p>' % (headerstrong(role=name_role, query=0), ) + if users: + details += usertable + else: + details += '<p>no users connected.</p>' + # show connected authorizations + details += '<p>authorizations for %s:</p>' % (headerstrong(role=name_role, query=0), ) + if actions: + details += actiontable + else: + details += '<p>no authorizations connected</p>' + + return details + + + +def perform_adduserrole(req, id_role='0', email_user_pattern='', id_user='0', confirm=0): + """create connection between user and role. + + id_role - id of the role to add user to + + email_user_pattern - search for users using this pattern + + id_user - id of user to add to the role. """ + + if not is_adminuser(req): return mustloginpage(req) + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + title = 'Add user to role ' + subtitle = 'step 1 - select a role' + + output = createroleselect(id_role=id_role, + action="adduserrole", + step=1, + roles=acca.acc_getAllRoles()) + + # role is selected + if id_role != "0": + title += name_role + + subtitle = 'step 2 - search for users' + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">2. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="adduserrole", + text=text, + button="search for users", + id_role=id_role) + + # pattern is entered + if email_user_pattern: + # users with matching email-address + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + # users that are connected + users2 = run_sql("""SELECT DISTINCT u.id, u.email + FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user + WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s' + ORDER BY u.id """ % (id_role, email_user_pattern)) + + # no users that match the pattern + if not (users1 or users2): + output += 'no qualified users, try new search' + # show matching users + else: + subtitle = 'step 3 - select a user' + + users = [] + extrausers = [] + for (id, email) in users1: + if (id, email) not in users2: users.append([id,email,'']) + for (id, email) in users2: + extrausers.append([-id, email,'']) + + output += createuserselect(id_user=id_user, + action="adduserrole", + step=3, + users=users, + extrausers=extrausers, + button="add this user", + id_role=id_role, + email_user_pattern=email_user_pattern) + + try: id_user = int(id_user) + except ValueError: pass + # user selected already connected to role + if id_user < 0: + output += '<p>users in brackets are already attached to the role, try another one</p>' + # a user is selected + elif email_out: + subtitle = "step 4 - confirm to add user" + + output += createhiddenform(action="adduserrole", + text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role), + id_role=id_role, + email_user_pattern=email_user_pattern, + id_user=id_user, + confirm=1) + + # it is confirmed that this user should be added + if confirm: + # add user + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm user added' + output += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role) + else: + subtitle = 'step 5 - user could not be added' + output += '<p>sorry, but user could not be added.</p>' + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + </dl> + """ + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output, extra]) + + +def perform_addroleuser(req, email_user_pattern='', id_user='0', id_role='0', confirm=0): + """delete connection between role and user. + + id_role - id of role to disconnect + + id_user - id of user to disconnect. """ + + if not is_adminuser(req): return mustloginpage(req) + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + title = 'Connect user to roles' + subtitle = 'step 1 - search for users' + + # clean email search string + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">1. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output = createhiddenform(action='addroleuser', + text=text, + button='search for users', + id_role=id_role) + + if email_user_pattern: + subtitle = 'step 2 - select user' + + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + users = [] + for (id, email) in users1: users.append([id, email, '']) + + if not users: + output += '<p>no qualified users, try new search</p>' + else: + output += createuserselect(id_user=id_user, + action='addroleuser', + step=2, + users=users, + button='select user', + email_user_pattern=email_user_pattern) + + if int(id_user): + subtitle = 'step 3 - select role' + + # roles the user is connected to + role_ids = acca.acc_getUserRoles(id_user=id_user) + # all the roles + all_roles = acca.acc_getAllRoles() + + # sort the roles in connected and not connected roles + con_roles = [] + not_roles = [] + for (id, name, description) in all_roles: + if (id, ) in role_ids: con_roles.append([-id, name, description]) + else: not_roles.append([id, name, description]) + + # create roleselect + output += createroleselect(id_role=id_role, + action='addroleuser', + step=3, + roles=not_roles, + extraroles=con_roles, + button='add this role', + email_user_pattern=email_user_pattern, + id_user=id_user) + + if int(id_role) < 0: + output += '<p>roles in brackets are already connected to the user, try another one<p>' + elif int(id_role): + subtitle = 'step 4 - confirm to add role to user' + + output += createhiddenform(action='addroleuser', + text='add role <strong>%s</strong> to user <strong>%s</strong>?' % (name_role, email_out), + email_user_pattern=email_user_pattern, + id_user=id_user, + id_role=id_role, + confirm=1) + + if confirm: + # add role + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm role added' + output += '<p>confirm: role <strong>%s</strong> added to user <strong>%s</strong>.</p>' % (name_role, email_out) + else: + subtitle = 'step 5 - role could not be added' + output += '<p>sorry, but role could not be added</p>' + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + </dl> + """ + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output, extra]) + + +def perform_deleteuserrole(req, id_role='0', id_user='0', reverse=0, confirm=0): + """delete connection between role and user. + + id_role - id of role to disconnect + + id_user - id of user to disconnect. """ + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Delete user from role' + email_user = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + output = '' + + if reverse in [0, '0']: + subtitle='step 1 - select the role' + output += createroleselect(id_role=id_role, + action="deleteuserrole", + step=1, + roles=acca.acc_getAllRoles()) + + if id_role != "0": + subtitle = 'step 2 - select the user' + output += createuserselect(id_user=id_user, + action="deleteuserrole", + step=2, + users=acca.acc_getRoleUsers(id_role=id_role), + id_role=id_role) + + else: + # show only users connected to a role + users = run_sql("""SELECT DISTINCT(u.id), u.email, u.note + FROM user u LEFT JOIN user_accROLE ur + ON u.id = ur.id_user + WHERE ur.id_accROLE != 'NULL' AND u.email != '' + ORDER BY id """) + + has_roles = 1 + + # check if the user is connected to any roles + for (id, email, note) in users: + if str(id) == str(id_user): break + else: + subtitle = 'step 1 - user not connected' + output += '<p>no need to remove roles from this user,<br>user <strong>%s</strong> is not connected to any roles.</p>' % (email_user, ) + has_roles, id_user = 0, '0' # stop the rest of the output below... + + + if has_roles: + output += createuserselect(id_user=id_user, + action="deleteuserrole", + step=1, + users=users, + reverse=reverse) + + if id_user != "0": + subtitle = 'step 2 - select the user' + + role_ids = acca.acc_getUserRoles(id_user=id_user) + all_roles = run_sql("""SELECT id, name, description FROM accROLE ORDER BY id """) + roles = [] + for (id, name, desc) in all_roles: + if (id, ) in role_ids: roles.append([id, name, desc]) + + output += createroleselect(id_role=id_role, + action="deleteuserrole", + step=2, + roles=roles, + id_user=id_user, + reverse=reverse) + + if id_role != '0' and id_user != '0': + subtitle = 'step 3 - confirm delete of user' + output += createhiddenform(action="deleteuserrole", + text='<span class="adminlabel">3. confirm</span> delete user %s from %s?' % (headerstrong(user=id_user), headerstrong(role=id_role)), + id_role=id_role, + id_user=id_user, + reverse=reverse, + confirm=1) + + if confirm: + res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role) + if res: + subtitle = 'step 4 - confirm delete of user' + output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role) + else: + subtitle = 'step 4 - user could not be deleted' + output += 'sorry, but user could not be deleted<br>user is probably already deleted.' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showuserdetails(req, id_user=0): + """show the details of a user. """ + + if not is_adminuser(req): return mustloginpage(req) + + if id_user not in [0, '0']: + output = userdetails(id_user=id_user) + + extra = """ + <dl> + <dt><a href="addroleuser?id_user=%s">Connect role</a></dt> + <dd>connect a role to the user.</dd> + </dl> + """ % (id_user, ) + + body = [output, extra] + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show User Details', + subtitle='show user details', + body=body) + + +def userdetails(id_user=0): + """create the string to show details about a user. """ + + # find necessary details + email_user = acca.acc_getUserEmail(id_user=id_user) + + userroles = acca.acc_getUserRoles(id_user=id_user) + conn_roles = [] + + # find connected roles + for (id, name, desc) in acca.acc_getAllRoles(): + if (id, ) in userroles: + conn_roles.append([id, name, desc]) + conn_roles[-1].append('<a href="showroledetails?id_role=%s">show details</a>' % (id, )) + + if conn_roles: + # print details + details = '<p>roles connected to user <strong>%s</strong></p>' % (email_user, ) + details += tupletotable(header=['id', 'name', 'description', ''], tuple=conn_roles) + else: + details = '<p>no roles connected to user <strong>%s</strong>.</p>' % (email_user, ) + + return details + +def perform_addauthorization(req, id_role="0", id_action="0", optional=0, reverse="0", confirm=0, **keywords): + """ form to add new connection between user and role: + + id_role - role to connect + + id_action - action to connect + + reverse - role or action first? """ + + if not is_adminuser(req): return mustloginpage(req) + + # values that might get used + name_role = acca.acc_getRoleName(id_role=id_role) or id_role + name_action = acca.acc_getActionName(id_action=id_action) or id_action + optional = optional == 'on' and 1 or int(optional) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + # create the page according to which step the user is on + # role -> action -> arguments + if reverse in ["0", 0]: + subtitle = 'step 1 - select role' + output = createroleselect(id_role=id_role, + action="addauthorization", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + if id_role != "0": + subtitle = 'step 2 - select action' + rolacts = acca.acc_getRoleActions(id_role) + allhelp = acca.acc_getAllActions() + allacts = [] + for r in allhelp: + if r not in rolacts: allacts.append(r) + output += createactionselect(id_action=id_action, + action="addauthorization", + step=2, + actions=rolacts, + extraactions=allacts, + id_role=id_role, + reverse=reverse) + # action -> role -> arguments + else: + subtitle = 'step 1 - select action' + output = createactionselect(id_action=id_action, + action="addauthorization", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + if id_action != "0": + subtitle = 'step 2 - select role' + actroles = acca.acc_getActionRoles(id_action) + allhelp = acca.acc_getAllRoles() + allroles = [] + for r in allhelp: + if r not in actroles: allroles.append(r) + output += createroleselect(id_role=id_role, + action="addauthorization", + step=2, + roles=actroles, + extraroles=allroles, + id_action=id_action, + reverse=reverse) + + # ready for step 3 no matter which direction we took to get here + if id_action != "0" and id_role != "0": + subtitle = 'step 3 - enter values for the keywords\n' + + output += """ + <form action="addauthorization" method="POST"> + <input type="hidden" name="id_role" value="%s"> + <input type="hidden" name="id_action" value="%s"> + <input type="hidden" name="reverse" value="%s"> + """ % (id_role, id_action, reverse) + + res_keys = acca.acc_getActionKeywords(id_action=id_action) + + if not res_keys: + output += """ + <input type="hidden" name="confirm" value="1"> + create connection between %s? + <input class="adminbutton" type="submit" value="confirm"> + </form> + """ % (headerstrong(role=name_role, action=name_action, query=0), ) + + + else: + optionalargs = acca.acc_getActionIsOptional(id_action=id_action) + + output += '<span class="adminlabel">3. arguments</span><br>' + if optionalargs: + output += """ + <p> + <input type="checkbox" name="optional" %s /> + create connection without the need for arguments + </p> + """ % (optional and 'checked="checked"' or '', ) + + allkeys = 1 + for key in res_keys: + output += '<span class="adminlabel">%s </span>\n <input class="admin_wvar" type="text" name="%s"' % (key, key) + try: + val = keywords[key] = cleanstring_argumentvalue(keywords[key]) + if val: output += 'value="%s" ' % (val, ) + else: allkeys = 0 + except KeyError: allkeys = 0 + output += ' /> <br>\n' + output = output[:-5] + ' <input class="adminbutton" type="submit" value="create entry -->" />\n' + output += '</form>\n' + + # ask for confirmation + if allkeys not in ["0", 0] or optional: + keys = keywords.keys() + keys.reverse() + subtitle = 'step 4 - confirm add of authorization\n' + + text = """ + create connection between <br> + %s <br> + """ % (headerstrong(role=name_role, action=name_action, query=0), ) + + if optional: + text += 'withouth arguments' + keywords = {} + else: + for key in keys: + text += '<strong>%s</strong>: %s \n' % (key, keywords[key]) + + output += createhiddenform(action="addauthorization", + text=text, + id_role=id_role, + id_action=id_action, + reverse=reverse, + confirm=1, + optional=optional, + **keywords) + + # show existing authorizations + res = acca.acc_findPossibleActions(id_role, id_action) + output += '<p>existing authorizations:</p>' + if res: + output += tupletotable(header=res[0], tuple=res[1:]) + # shortcut to modifying authorizations + extra += """ + <dl> + <dt><a href="modifyauthorizations?id_role=%s&id_action=%s&reverse=%s">Modify authorizations</a></dt> + <dd>modify the existing authorizations.<dd> + </dl> """ % (id_role, id_action, reverse) + + else: output += '<p>no details to show</p>' + + + # user confirmed to add entries + if confirm: + subtitle = 'step 5 - confirm authorization added' + res1 = acca.acc_addRoleActionArguments_names(name_role=name_role, + name_action=name_action, + arglistid=-1, + optional=optional, + **keywords) + # newentries = '' + + if res1: + res2 = acca.acc_findPossibleActions(id_role, id_action) + arg = res1[0][3] # the arglistid + new = [res2[0]] + for row in res2[1:]: + if row[0] == arg: new.append(row) + + newauths = tupletotable(header=new[0], tuple=new[1:]) + newentries = tupletotable(header=['role id', 'action id', 'argument id', '#'], tuple=res1) + + st = 'style="vertical-align: top"' + output += """ + <p>new authorization and entries:</p> + <table><tr> + <td class="admintd" %s>%s</td> + <td class="admintd" %s>%s</td> + </tr></table> """ % (st, newauths, st, newentries) + + else: output += '<p>sorry, authorization could not be added,<br>it probably already exists</p>' + + # trying to put extra link on the right side + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title = 'Create entry for new authorization', + subtitle=subtitle, + body=body) + + +def perform_deleteroleaction(req, id_role="0", id_action="0", reverse=0, confirm=0): + """delete all connections between a role and an action. + + id_role - id of the role + + id_action - id of the action + + reverse - 0: ask for role first + 1: ask for action first""" + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Remove action from role ' + + if reverse in ["0", 0]: + # select role -> action + subtitle = 'step 1 - select a role' + output = createroleselect(id_role=id_role, + action="deleteroleaction", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + + if id_role != "0": + rolacts = acca.acc_getRoleActions(id_role=id_role) + subtitle = 'step 2 - select the action' + output += createactionselect(id_action=id_action, + action="deleteroleaction", + step=2, + actions=rolacts, + reverse=reverse, + id_role=id_role, + button="remove connection and all authorizations") + else: + # select action -> role + subtitle = 'step 1 - select an action' + output = createactionselect(id_action=id_action, + action="deleteroleaction", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + + if id_action != "0": + actroles = acca.acc_getActionRoles(id_action=id_action) + subtitle = 'step 2 - select the role' + output += createroleselect(id_role=id_role, + action="deleteroleaction", + step=2, + roles=actroles, + button="remove connection and all authorizations", + id_action=id_action, + reverse=reverse) + + if id_action != "0" and id_role != "0": + subtitle = 'step 3 - confirm remove of action' + # ask for confirmation + + res = acca.acc_findPossibleActions(id_role, id_action) + + if res: + output += '<p>authorizations that also will be deleted:</p>' + output += tupletotable(header=res[0], tuple=res[1:]) + + output += createhiddenform(action="deleteroleaction", + text='remove action %s from %s' % (headerstrong(action=id_action), headerstrong(role=id_role)), + confirm=1, + id_role=id_role, + id_action=id_action, + reverse=reverse) + else: + output += 'no authorizations' + + # confirmation is given + if confirm: + subtitle = 'step 4 - confirm remove of action ' + res = acca.acc_deleteRoleAction(id_role=id_role, id_action=id_action) + if res: + output += '<p>confirm: removed %s from %s<br>' % (headerstrong(action=id_action), headerstrong(role=id_role)) + output += '<strong>%s</strong> entries were removed.</p>' % (res, ) + else: + output += '<p>sorry, no entries could be removed.</p>' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_modifyauthorizations(req, id_role="0", id_action="0", reverse=0, confirm=0, errortext='', sel='', authids=[]): + """given ids of a role and an action, show all possible action combinations + with checkboxes and allow user to access other functions. + + id_role - id of the role + + id_action - id of the action + + reverse - 0: ask for role first + 1: ask for action first + + sel - which button and modification that is selected + + errortext - text to print when no connection exist between role and action + + authids - ids of checked checkboxes """ + + if not is_adminuser(req): return mustloginpage(req) + + name_role = acca.acc_getRoleName(id_role) + name_action = acca.acc_getActionName(id_action) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + if reverse in ["0", 0]: + # role -> action + subtitle = 'step 1 - select the role' + output = createroleselect(id_role=id_role, + action="modifyauthorizations", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + + if id_role != "0": + rolacts = acca.acc_getRoleActions(id_role=id_role) + subtitle = 'step 2 - select the action' + output += createactionselect(id_action=id_action, + action="modifyauthorizations", + step=2, + actions=rolacts, + id_role=id_role, + reverse=reverse) + else: + # action -> role + subtitle = 'step 1 - select the action' + output = createactionselect(id_action=id_action, + action="modifyauthorizations", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + if id_action != "0": + actroles = acca.acc_getActionRoles(id_action=id_action) + subtitle = 'step 2 - select the role' + output += createroleselect(id_role=id_role, + action="modifyauthorizations", + step=2, + roles=actroles, + id_action=id_action, + reverse=reverse) + + if errortext: output += '<p>%s</p>' % (errortext, ) + + if id_role != "0" and id_action != "0": + # shortcut to modifying authorizations + extra += """ + <dl> + <dt><a href="addauthorization?id_role=%s&id_action=%s&reverse=%s">Add authorizations</a></dt> + <dd>Add and authorization to the existing.</dd> + </dl> """ % (id_role, id_action, reverse) + + # back to the main area + if type(authids) is not list: authids = [authids] + subtitle = 'step 3 - select groups and modification' + + # get info + res = acca.acc_findPossibleActions(id_role, id_action) + + # clean the authids + hiddenids = [] + if sel in ['delete selected']: + hiddenids = authids[:] + elif sel in ['split groups', 'merge groups']: + for authid in authids: + arghlp = res[int(authid)][0] + if authid not in hiddenids and arghlp not in [-1, '-1', 0, '0']: hiddenids.append(authid) + authids = hiddenids[:] + + if confirm: + # do selected modification and output with new authorizations + if sel == 'split groups': + res = splitgroups(id_role, id_action, authids) + elif sel == 'merge groups': + res = mergegroups(id_role, id_action, authids) + elif sel == 'delete selected': + res = deleteselected(id_role, id_action, authids) + authids = [] + res = acca.acc_findPossibleActions(id_role, id_action) + output += 'authorizations after <strong>%s</strong>.<br>\n' % (sel, ) + + elif sel and authids: + output += 'confirm choice of authorizations and modification.<br>\n' + else: + output += 'select authorizations and perform modification.<br>\n' + + if not res: + errortext='all connections deleted, try different ' + if reverse in ["0", 0]: + return perform_modifyauthorizations(req=req, id_role=id_role, errortext=errortext + 'action.') + else: + return perform_modifyauthorizations(req=req, id_action=id_action, reverse=reverse, errortext=errortext + 'role.') + + # display + output += modifyauthorizationsmenu(id_role, id_action, header=res[0], tuple=res[1:], checked=authids, reverse=reverse) + + if sel and authids: + # form with hidden authids + output += '<form action="%s" method="POST">\n' % ('modifyauthorizations', ) + + for hiddenid in hiddenids: + output += '<input type="hidden" name="authids" value="%s" />\n' % (hiddenid, ) + + # choose what to do + if sel == 'split groups': + output += '<p>split groups containing:</p>' + elif sel == 'merge groups': + output += '<p>merge groups containing:</p>' + elif sel == 'delete selected': + output += '<p>delete selected entries:</p>' + + extracolumn = '<input type="checkbox" name="confirm" value="1" />\n' + extracolumn += '<input class="adminbutton" type="submit" value="confirm" />\n' + + # show the entries here... + output += tupletotable_onlyselected(header=res[0], + tuple=res[1:], + selected=hiddenids, + extracolumn=extracolumn) + + output += '<input type="hidden" name="id_role" value="%s" />\n' % (id_role, ) + output += '<input type="hidden" name="id_action" value="%s" />\n' % (id_action, ) + output += '<input type="hidden" name="sel" value="%s" />\n' % (sel, ) + output += '<input type="hidden" name="reverse" value="%s" />\n' % (reverse, ) + output += '</form>' + + # tried to perform modification without something selected + elif sel and not authids and not confirm: + output += '<p>no valid groups selected</p>' + + # trying to put extra link on the right side + try: body = [output, extra] + except NameError: body = [output] + + # Display the page + return index(req=req, + title='Modify Authorizations', + subtitle=subtitle, + body=body) + + +def modifyauthorizationsmenu(id_role, id_action, tuple=[], header=[], checked=[], reverse=0): + """create table with header and checkboxes, used for multiple choice. + makes use of tupletotable to add the actual table + + id_role - selected role, hidden value in the form + + id_action - selected action, hidden value in the form + + tuple - all rows to be put in the table (with checkboxes) + + header - column headers, empty strings added at start and end + + checked - ids of rows to be checked """ + + if not tuple: + return 'no authorisations...' + + argnum = len(acca.acc_getActionKeywords(id_action=id_action)) + + tuple2 = [] + for t in tuple: tuple2.append(t[:]) + + tuple2 = addcheckboxes(datalist=tuple2, name='authids', startindex=1, checked=checked) + + hidden = '<input type="hidden" name="id_role" value="%s" /> \n' % (id_role, ) + hidden += '<input type="hidden" name="id_action" value="%s" /> \n' % (id_action, ) + hidden += '<input type="hidden" name="reverse" value="%s" /> \n' % (reverse, ) + + + button = '<input type="submit" class="adminbutton" value="delete selected" name="sel" />\n' + if argnum > 1: + button += '<input type="submit" class="adminbutton" value="split groups" name="sel" />\n' + button += '<input type="submit" class="adminbutton" value="merge groups" name="sel" />\n' + + hdrstr = '' + for h in [''] + header + ['']: hdrstr += ' <th class="adminheader">%s</th>\n' % (h, ) + if hdrstr: hdrstr = ' <tr>\n%s\n </tr>\n' % (hdrstr, ) + + output = '<form action="modifyauthorizations" method="POST">\n' + output += '<table class="admin_wvar_nomargin"> \n' + output += hdrstr + output += '<tr><td>%s</td></tr>\n' % (hidden, ) + + output += '<tr>' + for data in tuple2[0]: output += '<td class="admintd">%s</td>\n' % (data,) + output += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n' % (len(tuple2), button) + + output += '</tr>\n' + for row in tuple2[1:]: + output += ' <tr>\n' + for data in row: output += '<td class="admintd">%s</td>\n' % (data,) + output += ' </tr>\n' + + output += '</table>\n</form>\n' + + return output + + +def splitgroups(id_role=0, id_action=0, authids=[]): + """get all the old ones, gather up the arglistids find a list of + arglistidgroups to be split, unique get all actions in groups outside + of the old ones, (old arglistid is allowed). + + show them like in showselect. """ + + if not id_role or not id_action or not authids: + return 0 + + # find all the actions + datalist = acca.acc_findPossibleActions(id_role, id_action) + + if type(authids) is str: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + # argumentlistids of groups to be split + splitgrps = [] + for authid in authids: + hlp = datalist[authid][0] + if hlp not in splitgrps and authid in range(1,len(datalist)): + splitgrps.append(hlp) + + # split groups and return success or failure + result = 1 + for splitgroup in splitgrps: + result = 1 and acca.acc_splitArgumentGroup(id_role, id_action, splitgroup) + + return result + + +def mergegroups(id_role=0, id_action=0, authids=[]): + """get all the old ones, gather up the argauthids find a list + of arglistidgroups to be split, unique get all actions in groups + outside of the old ones, (old arglistid is allowed). + + show them like in showselect.""" + + if not id_role or not id_action or not authids: + return 0 + + datalist = acca.acc_findPossibleActions(id_role, id_action) + + if type(authids) is str: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + # argumentlistids of groups to be merged + mergegroups = [] + for authid in authids: + hlp = datalist[authid][0] + if hlp not in mergegroups and authid in range(1, len(datalist)): + mergegroups.append(hlp) + + # merge groups and return success or failure + if acca.acc_mergeArgumentGroups(id_role, id_action, mergegroups): + return 1 + else: + return 0 + + + +def deleteselected(id_role=0, id_action=0, authids=[]): + """delete checked authorizations/possible actions, ids in authids. + + id_role - role to delete from + + id_action - action to delete from + + authids - listids for which possible actions to delete.""" + + if not id_role or not id_action or not authids: + return 0 + + if type(authids) in [str, int]: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + result = acca.acc_deletePossibleActions(id_role=id_role, + id_action=id_action, + authids=authids) + + return result + + +def addadminbox(header='', datalist=[], cls="admin_wvar"): + """used to create table around main data on a page, row based. + + header - header on top of the table + + datalist - list of the data to be added row by row + + cls - possible to select wich css-class to format the look of the table.""" + + try: per = str(100 // len(datalist)) + '%' + except ZeroDivisionError: per = 1 + + output = '<table class="%s" ' % (cls, ) + 'width="100%">\n' + output += """ + <thead> + <tr> + <th class="adminheaderleft" colspan="%s">%s</th> + </tr> + </thead> + <tbody> + """ % (len(datalist), header) + for row in [datalist]: + output += ' <tr>\n' + for data in row: + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % (per, data) + output += ' </tr>\n' + output += """ + </tbody> + </table> + """ + + return output + + +def addadminbox(header='', datalist=[], cls="admin_wvar"): + """used to create table around main data on a page, row based. + + header - header on top of the table + + datalist - list of the data to be added row by row + + cls - possible to select wich css-class to format the look of the table.""" + + if len(datalist) == 1: per = 100 + else: per = 75 + + output = '<table class="%s" ' % (cls, ) + 'width="100%">\n' + output += """ + <thead> + <tr> + <th class="adminheaderleft" colspan="%s">%s</th> + </tr> + </thead> + <tbody> + """ % (len(datalist), header) + + output += ' <tr>\n' + + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % (per, datalist[0]) + + if len(datalist) > 1: + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % ('25%', datalist[1]) + + output += ' </tr>\n' + + output += """ + </tbody> + </table> + """ + + return output + + +def adderrorbox(header='', datalist=[]): + """used to create table around main data on a page, row based""" + + try: perc= str(100 // len(datalist)) + '%' + except ZeroDivisionError: perc= 1 + + output = '<table class="errorbox" width="100%">' + output += '<thead><tr><th class="errorboxheader" colspan="%s">%s</th></tr></thead>' % (len(datalist), header) + output += '<tbody>' + for row in [datalist]: + output += '<tr>' + for data in row: + output += '<td style="vertical-align: top; margin-top: 5px; width: %s;">' % (perc, ) + output += data + output += '</td>' + output += '</tr>' + output += '</tbody></table>' + + return output + + +def tupletotable(header=[], tuple=[], start='', end='', extracolumn=''): + """create html table for a tuple. + + header - optional header for the columns + + tuple - create table of this + + start - text to be added in the beginning, most likely beginning of a form + + end - text to be added in the end, mot likely end of a form. + + extracolumn - mainly used to put in a button. """ + + tblstr = '' + for h in header + ['']: + tblstr += ' <th class="adminheader">%s</th>\n' % (h, ) + if tblstr: tblstr = ' <tr>\n%s\n </tr>\n' % (tblstr, ) + + tblstr = start + '<table class="admin_wvar_nomargin">\n' + tblstr + + # extra column + try: + extra = '<tr>' + row = tuple[0] + if type(row) not in [int, long, str, dict]: + for data in row: extra += '<td class="admintd">%s</td>\n' % (data,) + else: + extra += ' <td class="admintd">%s</td>\n' % (row, ) + extra += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n</tr>\n' % (len(tuple), extracolumn) + except IndexError: + extra = '' + tblstr += extra + + + for row in tuple[1:]: + tblstr += ' <tr>\n' + if type(row) not in [int, long, str, dict]: + for data in row: tblstr += '<td class="admintd">%s</td>\n' % (data,) + else: + tblstr += ' <td class="admintd">%s</td>\n' % (row, ) + tblstr += ' </tr> \n' + + tblstr += '</table> \n ' + tblstr += end + + return tblstr + + +def tupletotable_onlyselected(header=[], tuple=[], selected=[], start='', end='', extracolumn=''): + """create html table for a tuple. + + header - optional header for the columns + + tuple - create table of this + + selected - indexes of selected rows in the tuple + + start - put this in the beginning + + end - put this in the beginning + + extracolumn - mainly used to put in a button""" + + tuple2 = [] + + for index in selected: + tuple2.append(tuple[int(index)-1]) + + return tupletotable(header=header, + tuple=tuple2, + start=start, + end=end, + extracolumn=extracolumn) + + +def addcheckboxes(datalist=[], name='authids', startindex=1, checked=[]): + """adds checkboxes in front of the listdata. + + datalist - add checkboxes in front of this list + + name - name of all the checkboxes, values will be associated with this name + + startindex - usually 1 because of the header + + checked - values of checkboxes to be pre-checked """ + + if not type(checked) is list: checked = [checked] + for row in datalist: + if 1 or row[0] not in [-1, "-1", 0, "0"]: # always box, check another place + chkstr = str(startindex) in checked and 'checked="checked"' or '' + row.insert(0, '<input type="checkbox" name="%s" value="%s" %s />' % (name, startindex, chkstr)) + else: + row.insert(0, '') + startindex += 1 + return datalist + + +def headeritalic(**ids): + """transform keyword=value pairs to string with value in italics. + + **ids - a dictionary of pairs to create string from """ + + output = '' + value = '' + table = '' + + for key in ids.keys(): + if key in ['User', 'user']: + value, table = 'email', 'user' + elif key in ['Role', 'role']: + value, table = 'name', 'accROLE' + elif key in ['Action', 'action']: + value, table = 'name', 'accACTION' + else: + if output: output += ' and ' + output += ' %s <i>%s</i>' % (key, ids[key]) + continue + + res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key])) + + if res: + if output: output += ' and ' + output += ' %s <i>%s</i>' % (key, res[0][0]) + + return output + + +def headerstrong(query=1, **ids): + """transform keyword=value pairs to string with value in strong text. + + **ids - a dictionary of pairs to create string from + + query - 1 -> try to find names to ids of role, user and action. + 0 -> do not try to find names, use the value passed on """ + + output = '' + value = '' + table = '' + + for key in ids.keys(): + if key in ['User', 'user']: + value, table = 'email', 'user' + elif key in ['Role', 'role']: + value, table = 'name', 'accROLE' + elif key in ['Action', 'action']: + value, table = 'name', 'accACTION' + else: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, ids[key]) + continue + + if query: + res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key])) + if res: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, res[0][0]) + else: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, ids[key]) + + return output + + +def startpage(): + """create the menu for the startpage""" + + body = """ + <table class="admin_wvar" width="100%s" summary=""> + <thead> + <tr> + <th class="adminheaderleft" colspan="2">Selection for Admin <i>%s</i></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> + <dl> + <dt><a href="webaccessadmin.py/rolearea">Role Area</a> + <dd>Main area to configure administration rights and authorization rules. + <dt><a href="webaccessadmin.py/actionarea">Action Area</a> + <dd>Configure administration rights with the actions as starting point. + <dt><a href="webaccessadmin.py/userarea">User Area</a> + <dd>Configure administration rights with the users as starting point. + <dt><a href="webaccessadmin.py/resetarea">Reset Area</a> + <dd>Reset roles, actions and authorizations. + </dl> + </td> + <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> </td> + </tr> + </tbody> + </table>""" % ('%', SUPERADMINROLE, '%', '%') + + return body + + +def perform_simpleauthorization(req, id_role=0, id_action=0): + """show a page with simple overview of authorizations between a + connected role and action. """ + + if not is_adminuser(req): return mustloginpage(req) + + res = acca.acc_findPossibleActions(id_role, id_action) + if res: + extra = createhiddenform(action='modifyauthorizations', + button='modify authorizations', + id_role=id_role, + id_action=id_action) + + output = '<p>authorizations for %s:</p>' % (headerstrong(action=id_action, role=id_role), ) + output += tupletotable(header=res[0], tuple=res[1:], extracolumn=extra) + else: + output = 'no details to show' + + return index(req=req, + title='Simple authorization details', + subtitle='simple authorization details', + body=[output]) + + +def perform_simpleroleusers(req, id_role=0): + """show a page with simple overview of a role and connected users. """ + + if not is_adminuser(req): return mustloginpage(req) + + res = acca.acc_getRoleUsers(id_role=id_role) + if res: + users = [] + for (id, name, dontcare) in res: users.append([id, name, '<a href="showuserdetails?id_user=%s">show user details</a>' + % (id, )]) + output = '<p>users connected to %s:</p>' % (headerstrong(role=id_role), ) + output += tupletotable(header=['id', 'name', ''], tuple=users) + else: + output = 'no users connected' + + return index(req=req, + title='Simple user details', + subtitle='simple user details', + body=[output]) + + +def createhiddenform(action="", text="", button="confirm", cnfrm='', **hidden): + """create select with hidden values and submit button + + action - name of the action to perform on submit + + text - additional text, can also be used to add non hidden input + + button - value/caption on the submit button + + cnfrm - if given, must check checkbox to confirm + + **hidden - dictionary with name=value pairs for hidden input """ + + output = '<form action="%s" method="POST">\n' % (action, ) + output += '<table>\n<tr><td>' + output += text + if cnfrm: + output += ' <input type="checkbox" name="confirm" value="1" />' + for key in hidden.keys(): + output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key]) + output += '</td><td style="vertical-align: bottom">' + output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, ) + output += '</td></tr></table>' + output += '</form>\n' + + return output + + +def createselect(id_input="0", label="", step=0, name="", + action="", list=[], extralist=[], + button="", **hidden): + """create form with select and hidden values + + id - the one to choose as selected if exists + + label - label shown to the left of the select + + name - the name of the select on which to reference it + + list - primary list to select from + + extralist - list of options to be put in paranthesis + + button - the value/text to be put on the button + + **hidden - name=value pairs to be put as hidden in the form. """ + + step = step and '%s. ' % step or '' + + output = '<form action="%s" method="POST">\n' % (action, ) + output += ' <span class="adminlabel">%s</span>\n' % (step + label, ) + output += ' <select name="%s" class="admin_w200">\n' % (name, ) + if not list and not extralist: + output += ' <option value="0">no %ss to select from</option>\n' % (label.split()[-1], ) + else: + output += ' <option value="0">%s</option>\n' % (label, ) + for (id, email, dontcare) in list: + if str(id) == id_input: output += ' <option value="%s" selected="selected">%s</option>\n' % (id, email) + else: output += ' <option value="%s">%s</option>\n' % (id, email) + for (id, email, dontcare) in extralist: + if str(id) == id_input: output += ' <option value="%s" selected="selected">(%s)</option>\n' % (id, email) + else: output += ' <option value="%s">(%s)</option>\n' % (id, email) + output += ' </select>\n' + for key in hidden.keys(): + output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key]) + output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, ) + output += '</form>\n' + + return output + + +def createactionselect(id_action="0", label="select action", step=0, name="id_action", + action="", actions=[], extraactions=[], + button="select action", **hidden): + """create a select for roles in a form. see createselect.""" + + return createselect(id_input=id_action, label=label, step=step, name=name, + action=action, list=actions, extralist=extraactions, + button=button, **hidden) + + +def createroleselect(id_role="0", label="select role", step=0, name="id_role", + action="", roles=[], extraroles=[], + button="select role", **hidden): + """create a select for roles in a form. see createselect.""" + + return createselect(id_input=id_role, label=label, step=step, name=name, + action=action, list=roles, extralist=extraroles, + button=button, **hidden) + + +def createuserselect(id_user="0", label="select user", step=0, name="id_user", + action="", users=[], extrausers=[], + button="select user", **hidden): + """create a select for users in a form.see createselect.""" + + return createselect(id_input=id_user, label=label, step=step, name=name, + action=action, list=users, extralist=extrausers, + button=button, **hidden) + + +def cleanstring(str='', comma=0): + """clean all the strings before submitting to access control admin. + remove characters not letter, number or underscore, also remove leading + underscores and numbers. return cleaned string. + + str - string to be cleaned + + comma - 1 -> allow the comma to divide multiple arguments + 0 -> wash commas as well """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_,]', '', str) + + # split string on commas + items = str.split(',') + str = '' + for item in items: + if not item: continue + if comma and str: str += ',' + # create valid variable names + str += re.sub(r'^([0-9_])*', '', item) + + return str + + +def cleanstring_argumentvalue(str=''): + """clean the value of an argument before submitting it. + allowed characters: a-z A-Z 0-9 _ and space + + str - string to be cleaned """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_ .]', '', str) + # trim leading and ending spaces + str = re.sub(r'^ *| *$', '', str) + + return str + + +def cleanstring_email(str=''): + """clean the string and return a valid email address. + + str - string to be cleaned """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_.@]', '', str) + + return str + + +def check_email(str=''): + """control that submitted emails are correct. + this little check is not very good, but better than nothing. """ + + r = re.compile(r'(.)+\@(.)+\.(.)+') + return r.match(str) and 1 or 0 diff --git a/modules/webaccess/lib/webaccessadmin_lib.py.wml b/modules/webaccess/lib/webaccessadmin_lib.py.wml new file mode 100644 index 000000000..723c49136 --- /dev/null +++ b/modules/webaccess/lib/webaccessadmin_lib.py.wml @@ -0,0 +1,2537 @@ +## $Id$ +## Administrator interface for WebAccess + +## This file is part of the CERN Document Server Software (CDSware). +## Copyright (C) 2002 CERN. +## +## The CDSware is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2 of the +## License, or (at your option) any later version. +## +## The CDSware is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with CDSware; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +## read config variables: +#include "config.wml" +#include "configbis.wml" + +<protect>## $Id$</protect> +<protect>## DO NOT EDIT THIS FILE! IT WAS AUTOMATICALLY GENERATED FROM CDSware WML SOURCES.</protect> +"""CDSware WebAccess Administrator Interface.""" + +__lastupdated__ = """<: print `date +"%d %b %Y %H:%M:%S %Z"`; :>""" + +## fill config variables: +pylibdir = "<LIBDIR>/python" + +try: + import sys + sys.path.append('%s' % pylibdir) + import cdsware.access_control_engine as acce + import cdsware.access_control_admin as acca + reload(acce) + reload(acca) + import cgi + import re + + from cdsware.dbquery import run_sql + from cdsware.access_control_variables import SUPERADMINROLE, WEBACCESSACTION, DELEGATEADDUSERROLE + from cdsware.config import * + from cdsware.webpage import page, pageheaderonly, pagefooteronly + from cdsware.webuser import getUid, get_email + from mod_python import apache +except ImportError, e: + print "Error: %s" % e + import sys + sys.exit(1) + +__version__ = "$Id$" + + +def index(req, title='', body='', subtitle='', authorized=0): + """main function to show pages for webaccessadmin. + + 1. if user not logged in and administrator, show the mustlogin page + + 2. if used without body argument, show the startpage + + 3. show admin page with title, body, subtitle and navtrail. + + authorized - if 1, don't check if the user is allowed to be webadmin """ + + # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> > + # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> > + # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin</a> > """ + navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> > <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> """ + + if body and not authorized: navtrail_previous_links += '> <a class=navtrail href=<WEBURL>/admin/webaccess/webaccessadmin.py>Manage WebAccess</a>' + + id_user = getUid(req) + + if not authorized and not is_adminuser(req): return mustloginpage(req) + + elif not body: + title = 'Manage WebAccess' + body = startpage() + elif type(body) != str: body = addadminbox(subtitle, datalist=body) + + return page(title=title, + uid=id_user, + body=body, + navtrail=navtrail_previous_links, + lastupdated=__lastupdated__) + + +def mustloginpage(req): + """show a page asking the user to login.""" + + # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> > + # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> > + # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin Area</a>""" + navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> > <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> > """ + + return page(title='Authorization failure', + uid=getUid(req), + body=adderrorbox('try to login first', + datalist=["""You are not a user authorized to perform admin tasks, try to + <a href="http://cdsdev.cern.ch:8000/DEMODEV/youraccount.py/login">login</a>."""]), + navtrail=navtrail_previous_links, + lastupdated=__lastupdated__) + + +def is_adminuser(req): + """check if user is a registered administrator. """ + + id_user = getUid(req) + return acce.acc_authorize_action(id_user, WEBACCESSACTION) + + +def perform_rolearea(req): + """create the role area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + header = ['id', 'name', 'description', 'users', 'authorizations / actions', 'role', ''] + roles = acca.acc_getAllRoles() + + roles2 = [] + for (id, name, desc) in roles: + if len(desc) > 30: desc = desc[:30] + '...' + roles2.append([id, name, desc]) + for col in [(('add', 'adduserrole'), + ('remove', 'deleteuserrole')), + (('add', 'addauthorization'), + ('modify', 'modifyauthorizations'), + ('remove', 'deleteroleaction')), + (('delete', 'deleterole'), ), + (('show details', 'showroledetails'), )]: + roles2[-1].append('<a href="%s?id_role=%s">%s</a>' % (col[0][1], id, col[0][0])) + for (str, function) in col[1:]: + roles2[-1][-1] += ' / <a href="%s?id_role=%s">%s</a>' % (function, id, str) + + output = """ + <dl> + <dt>Users:</dt> + <dd>add or remove users from the access to a role and its priviliges.</dd> + <dt>Authorizations/Actions:</dt> + <dd>these terms means almost the same, but an authorization is a <br> + connection between a role and an action (possibly) containing arguments.</dd> + <dt>Roles:</dt> + <dd>see all the information attached to a role and decide if you want to<br>delete it.</dd> + </dl> + """ + + output += tupletotable(header=header, tuple=roles2) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + return index(req=req, + title='Role Administration', + subtitle='administration with roles as access point', + body=[output, extra]) + + +def perform_actionarea(req): + """create the action area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + header = ['id', 'name', 'authorizations/roles', 'action', ''] + actions = acca.acc_getAllActions() + + actions2 = [] + roles2 = [] + for (id, name, dontcare) in actions: + actions2.append([id, name]) + for col in [(('add', 'addauthorization'), + ('modify', 'modifyauthorizations'), + ('remove', 'deleteroleaction')), + (('delete', 'deleteaction'), ), + (('show details', 'showactiondetails'), )]: + actions2[-1].append('<a href="%s?id_action=%s&reverse=1">%s</a>' % (col[0][1], id, col[0][0])) + for (str, function) in col[1:]: + actions2[-1][-1] += ' / <a href="%s?id_action=%s&reverse=1">%s</a>' % (function, id, str) + + output = """ + <dl> + <dt>Authorizations/Roles:</dt> + <dd>these terms means almost the same, but an authorization is a <br> + connection between a role and an action (possibly) containing arguments.</dd> + <dt>Actions:</dt> + <dd>see all the information attached to an action and decide if you want to<br>delete it.</dd> + </dl> + """ + + output += tupletotable(header=header, tuple=actions2) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a> + <dd>go here to add a new role. + <dt><a href="addaction">Add new action</a> + <dd>go here to add a new action. + </dl> + """ + + return index(req=req, + title='Action Administration', + subtitle='administration with actions as access point', + body=[output, extra]) + + +def perform_userarea(req, email_user_pattern=''): + """create area to show info about users. """ + + if not is_adminuser(req): return mustloginpage(req) + + subtitle = 'step 1 - search for users' + + output = """ + <p> + search for users to display. + </p> """ + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">1. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="userarea", + text=text, + button="search for users") + + if email_user_pattern: + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id LIMIT 26""" % (email_user_pattern, )) + + if not users1: + output += '<p>no matching users</p>' + else: + subtitle = 'step 2 - select what to do with user' + + users = [] + for (id, email) in users1[:25]: + users.append([id, email]) + for col in [(('add', 'addroleuser'), + ('remove', 'deleteuserrole')), + (('show details', 'showuserdetails'), )]: + users[-1].append('<a href="%s?email_user_pattern=%s&id_user=%s">%s</a>' % (col[0][1], email_user_pattern, id, col[0][0])) + for (str, function) in col[1:]: + users[-1][-1] += ' / <a href="%s?email_user_pattern=%s&id_user=%s&reverse=1">%s</a>' % (function, email_user_pattern, id, str) + + output += '<p>found <strong>%s</strong> matching users</p>' % (len(users1), ) + output += tupletotable(header=['id', 'email', 'roles', ''], tuple=users) + + if len(users1) > 25: + output += '<p><strong>only showing the first 25 users, narrow your search...</strong></p>' + + return index(req=req, + title='User Administration', + subtitle=subtitle, + body=[output]) + + +def perform_resetarea(req): + """create the reset area menu page.""" + + if not is_adminuser(req): return mustloginpage(req) + + output = """ + <dl> + <dt><a href="resetdefaultsettings">Reset to Default Authorizations</a> + <dd>Remove all changes that has been done to the roles and <br> + add only the default authorization settings. + <dt><a href="adddefaultsettings">Add Default Authorizations</a> + <dd>Keep all changes and add the default authorization settings. + </dl> + """ + + return index(req=req, + title='Reset Authorizations', + subtitle='reseting to or adding default authorizations', + body=[output]) + + +def perform_resetdefaultsettings(req, superusers=[], confirm=0): + """delete all roles, actions and authorizations presently in the database + and add only the default roles. + only selected users will be added to superadmin, rest is blank """ + + if not is_adminuser(req): return mustloginpage(req) + + # cleaning input + if type(superusers) == str: superusers = [superusers] + + # remove not valid e-mails + for email in superusers: + if not check_email(email): superusers.remove(email) + + # instructions + output = """ + <p> + before you reset the settings, we need some users<br> + to connect to <strong>%s</strong>.<br> + enter as many e-mail adresses you want and press <strong>reset</strong>.<br> + <strong>confirm reset settings</strong> when you have added enough e-mails.<br> + <strong><SUPPORTEMAIL></strong> is added as default. + </p>""" % (SUPERADMINROLE, ) + + # add more superusers + output += """ + <p>enter user e-mail addresses: </p> + <form action="resetdefaultsettings" method="POST">""" + + for email in superusers: + output += ' <input type="hidden" name="superusers" value="%s" />' % (email, ) + + output += """ + <span class="adminlabel">e-mail</span> + <input class="admin_wvar" type="text" name="superusers" /> + <input class="adminbutton" type="submit" value="add e-mail" /> + </form>""" + + + if superusers: + # remove emails + output += """ + <form action="resetdefaultsettings" method="POST"> + have you entered wrong data? + <input class="adminbutton" type="submit" value="remove all e-mails" /> + </form> + """ + + # superusers confirm table + start = '<form action="resetdefaultsettings" method="POST">' + + extra = ' <input type="hidden" name="confirm" value="1" />' + for email in superusers: + extra += '<input type="hidden" name="superusers" value="%s" />' % (email, ) + extra += ' <input class="adminbutton" type="submit" value="confirm to reset settings" />' + + end = '</form>' + + output += '<p><strong>reset default settings</strong> with the users below? </p>' + output += tupletotable(header=['e-mail address'], + tuple=superusers, + start=start, + extracolumn=extra, + end=end) + + if confirm in [1, "1"]: + res = acca.acc_reset_default_settings(superusers) + if res: + output += '<p>successfully reset default settings</p>' + else: + output += '<p>sorry, could not reset default settings</p>' + + return index(req=req, + title='Reset Default Settings', + subtitle='reset settings', + body=[output]) + + +def perform_adddefaultsettings(req, superusers=[], confirm=0): + """add the default settings, and keep everything else. + probably nothing will be deleted, except if there has been made changes to the defaults.""" + + if not is_adminuser(req): return mustloginpage(req) + + # cleaning input + if type(superusers) == str: superusers = [superusers] + + # remove not valid e-mails + for email in superusers: + if not check_email(email): superusers.remove(email) + + # instructions + output = """ + <p> + before you add the settings, we need some users<br> + to connect to <strong>%s</strong>.<br> + enter as many e-mail adresses you want and press <strong>add</strong>.<br> + <strong>confirm add settings</strong> when you have added enough e-mails.<br> + <strong><SUPPORTEMAIL></strong> is added as default. + </p>""" % (SUPERADMINROLE, ) + + # add more superusers + output += """ + <p>enter user e-mail addresses: </p> + <form action="adddefaultsettings" method="POST">""" + + for email in superusers: + output += ' <input type="hidden" name="superusers" value="%s" />' % (email, ) + + output += """ + <span class="adminlabel">e-mail</span> + <input class="admin_wvar" type="text" name="superusers" /> + <input class="adminbutton" type="submit" value="add e-mail" /> + </form> + """ + + if superusers: + # remove emails + output += """ + <form action="adddefaultsettings" method="POST"> + have you entered wrong data? + <input class="adminbutton" type="submit" value="remove all e-mails" /> + </form> + """ + + # superusers confirm table + start = '<form action="adddefaultsettings" method="POST">' + + extra = ' <input type="hidden" name="confirm" value="1" />' + for email in superusers: + extra += '<input type="hidden" name="superusers" value="%s" />' % (email, ) + extra += ' <input class="adminbutton" type="submit" value="confirm to add settings" />' + + end = '</form>' + + output += '<p><strong>add default settings</strong> with the users below? </p>' + output += tupletotable(header=['e-mail address'], + tuple=superusers, + start=start, + extracolumn=extra, + end=end) + + if confirm in [1, "1"]: + res = acca.acc_add_default_settings(superusers) + if res: + output += '<p>successfully added default settings</p>' + else: + output += '<p>sorry, could not add default settings</p>' + + return index(req=req, + title='Add Default Settings', + subtitle='add settings', + body=[output]) + + +def perform_delegate_startarea(req): + """start area for lower level delegation of rights.""" + + subtitle = 'select what to do' + + output = '' + + if is_adminuser(req): + output += """ + <p> + You are also allowed to be in the <a href="../webaccessadmin.py">Main Admin Area</a> which gives you<br> + the access to the full functionality of WebAccess. + </p> + """ + + output += """ + <dl> + <dt><a href="delegate_adduserrole">Add users to roles</a> + <dd>add users to the roles you have delegation rights to. + <dt><a href="delegate_deleteuserrole">Remove users from roles</a> + <dd>remove users from the roles you have delegation rights to. + </dl> + """ + + return index(req=req, + title='Delegate Rights - start area', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_delegate_adduserrole(req, id_role=0, email_user_pattern='', id_user=0, confirm=0): + """let a lower level web admin add users to a limited set of roles. + + id_role - the role to connect to a user + + id_user - the user to connect to a role + + confirm - make the connection happen """ + + # finding the allowed roles for this user + id_admin = getUid(req) + id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) + actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action) + + allowed_roles = [] + for (id, arglistid, name_role_help) in actions[1:]: + id_role_help = acca.acc_getRoleId(name_role=name_role_help) + if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles: + allowed_roles.append([id_role_help, name_role_help, '']) + + output = '' + + if not allowed_roles: + subtitle = 'no delegation rights' + output += """ + <p> + You do not have the delegation rights over any roles.<br> + If you think you should have such rights, contact a WebAccess Administrator. + </p>""" + else: + subtitle = 'step 1 - select role' + + output += """ + <p> + Lower level delegation of access rights to roles.<br> + An administrator with all rights have to give you these rights. + </p>""" + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + output += createroleselect(id_role=id_role, step=1, name='id_role', + action='delegate_adduserrole', roles=allowed_roles) + + if str(id_role) != '0': + subtitle = 'step 2 - search for users' + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">2. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="delegate_adduserrole", + text=text, + button="search for users", + id_role=id_role) + + # pattern is entered + if email_user_pattern: + # users with matching email-address + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + # users that are connected + users2 = run_sql("""SELECT DISTINCT u.id, u.email + FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user + WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s' + ORDER BY u.id """ % (id_role, email_user_pattern)) + + # no users that match the pattern + if not (users1 or users2): + output += 'no qualified users, try new search' + # show matching users + else: + subtitle = 'step 3 - select a user' + + users = [] + extrausers = [] + for (id, email) in users1: + if (id, email) not in users2: users.append([id,email,'']) + for (id, email) in users2: + extrausers.append([-id, email,'']) + + output += createuserselect(id_user=id_user, + action="delegate_adduserrole", + step=3, + users=users, + extrausers=extrausers, + button="add this user", + id_role=id_role, + email_user_pattern=email_user_pattern) + + try: id_user = int(id_user) + except ValueError: pass + # user selected already connected to role + if id_user < 0: + output += '<p>users in brackets are already attached to the role, try another one</p>' + # a user is selected + elif email_out: + subtitle = "step 4 - confirm to add user" + + output += createhiddenform(action="delegate_adduserrole", + text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role), + id_role=id_role, + email_user_pattern=email_user_pattern, + id_user=id_user, + confirm=1) + + # it is confirmed that this user should be added + if confirm: + # add user + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm user added' + output += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role) + else: + subtitle = 'step 5 - user could not be added' + output += '<p>sorry, but user could not be added.</p>' + + return index(req=req, + title='Delegate Rights - add users to roles', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_delegate_deleteuserrole(req, id_role=0, id_user=0, confirm=0): + """let a lower level web admin remove users from a limited set of roles. + + id_role - the role to connect to a user + + id_user - the user to connect to a role + + confirm - make the connection happen """ + + subtitle = 'in progress...' + + output = '<p>in progress...</p>' + + # finding the allowed roles for this user + id_admin = getUid(req) + id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) + actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action) + + output = '' + + if not actions: + subtitle = 'no delegation rights' + output += """ + <p> + You do not have the delegation rights over any roles.<br> + If you think you should have such rights, contact a WebAccess Administrator. + </p>""" + else: + subtitle = 'step 1 - select role' + + output += """ + <p> + Lower level delegation of access rights to roles.<br> + An administrator with all rights have to give you these rights. + </p>""" + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + allowed_roles = [] + for (id, arglistid, name_role_help) in actions[1:]: + id_role_help = acca.acc_getRoleId(name_role=name_role_help) + if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles: + allowed_roles.append([id_role_help, name_role_help, '']) + + output += createroleselect(id_role=id_role, step=1, + action='delegate_deleteuserrole', roles=allowed_roles) + + if str(id_role) != '0': + subtitle = 'step 2 - select user' + + users = acca.acc_getRoleUsers(id_role) + + output += createuserselect(id_user=id_user, step=2, + action='delegate_deleteuserrole', users=users, + id_role=id_role) + + if str(id_user) != '0': + subtitle = 'step 3 - confirm delete of user' + email_user = acca.acc_getUserEmail(id_user=id_user) + + output += createhiddenform(action="delegate_deleteuserrole", + text='delete user %s from %s?' + % (headerstrong(user=id_user), headerstrong(role=id_role)), + id_role=id_role, + id_user=id_user, + confirm=1) + + if confirm: + res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role) + if res: + subtitle = 'step 4 - confirm user deleted from role' + output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role) + else: + subtitle = 'step 4 - user could not be deleted' + output += 'sorry, but user could not be deleted<br>user is probably already deleted.' + + return index(req=req, + title='Delegate Rights - remove users from roles', + subtitle=subtitle, + body=[output], + authorized=1) + + +def perform_addaction(req, name_action='', arguments='', optional='no', description='put description here.', confirm=0): + """form to add a new action with these values: + + name_action - name of the new action + + arguments - allowedkeywords, separated by whitespace + + description - optional description of the action""" + + if not is_adminuser(req): return mustloginpage(req) + + name_action = cleanstring(name_action) + arguments = cleanstring(arguments, comma=1) + + title = 'Add Action' + subtitle = 'step 1 - give values to the requested fields' + + output = """ + <form action="addaction" method="POST"> + <span class="adminlabel">action name </span> + <input class="admin_wvar" type="text" name="name_action" value="%s" /> <br> + <span class="adminlabel">arguments </span> + <input class="admin_wvar" type="text" name="arguments" value="%s" /> + <small>keywords for arguments, separate with comma, no whitespace.</small> <br> + <span class="adminlabel">optional arguments</span> + <select name="optional" class="admin_w200"> + <option value="no" selected="selected">no, not allowed</option> + <option value="yes" %s>yes, allowed</option> + </select><br> + <span class="adminlabel">description </span> + <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> + <input class="adminbutton" type="submit" value="add action" /> + </form> + """ % (name_action, arguments, optional == 'yes' and 'selected="selected"' or '', description) + + if name_action: + # description must be changed before it is submitted + if description == 'put description here.': internaldesc = '' + else: internaldesc = description + + if arguments: + subtitle = 'step 2 - confirm to add action with %s arguments' % (optional == 'yes' and 'optional' or '', ) + arguments = arguments.replace(' ', '') + text = 'add action with: <br>\n' + text += 'name: <strong>%s</strong><br>\n' % (name_action, ) + if internaldesc: + text += 'description: <strong>%s</strong><br>\n' % (description, ) + text += '%sarguments: <strong>%s</strong><br>' % (optional == 'yes' and 'optional ' or '', arguments) + text += 'optional: <strong>%s</strong>?' % (optional, ) + + else: + optional = 'no' + subtitle = 'step 2 - confirm to add action without arguments' + text = 'add action <strong>%s</strong> without arguments' % (name_action, ) + if internaldesc: text += '<br>\nand description: <strong>%s</strong>?\n' % (description, ) + else: text += '?\n' + + output += createhiddenform(action="addaction", + text=text, + name_action=name_action, + arguments=arguments, + optional=optional, + description=description, + confirm=1) + + if confirm not in ["0", 0]: + arguments = arguments.split(',') + result = acca.acc_addAction(name_action, + internaldesc, + optional, + *arguments) + + if result: + subtitle = 'step 3 - action added' + output += '<p>action added:</p>' + output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords', 'optional'], + tuple=[result]) + else: + subtitle = 'step 3 - action could not be added' + output += '<p>sorry, could not add action, <br>action with the same name probably exists.</p>' + + extra = """ + <dl> + <dt><a href="addauthorization?id_action=%s&reverse=1">Add authorization</a></dt> + <dd>start adding new authorizations to this action.</dd> + </dl> """ % (acca.acc_getActionId(name_action=name_action, )) + + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title=title, + body=body, + subtitle=subtitle) + + +def perform_deleteaction(req, id_action="0", confirm=0): + """show all roles connected, and ask for confirmation. + + id_action - id of action to delete """ + + if not is_adminuser(req): return mustloginpage(req) + + title='Delete Action' + subtitle='step 1 - select action to delete' + name_action = acca.acc_getActionName(id_action=id_action) + + output = createactionselect(id_action=id_action, + action="deleteaction", + step=1, + actions=acca.acc_getAllActions(), + button="delete action") + + if id_action != "0": + subtitle = 'step 2 - confirm the delete' + + output += actiondetails(id_action=id_action) + + if acca.acc_getActionRoles(id_action=id_action): + output += createhiddenform(action="deleteroleaction", + text="""rather delete only connection between this action + and a selected role?""", + id_action=id_action, + reverse=1, + button='go there') + + output += createhiddenform(action="deleteaction", + text=' delete action <strong>%s</strong> and all connections?' % (name_action, ), + confirm=1, + id_action=id_action) + + if confirm: + subtitle = 'step 3 - confirm delete of action' + res = acca.acc_deleteAction(id_action=id_action) + if res: + output += '<p>confirm: action <strong>%s</strong> deleted.<br>\n' % (name_action, ) + output += '%s entries deleted all in all.</p>\n' % (res, ) + else: + output += '<p>sorry, action could not be deleted.</p>\n' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showactiondetails(req, id_action): + """show the details of an action. """ + + if not is_adminuser(req): return mustloginpage(req) + + if id_action not in [0, '0']: + output = actiondetails(id_action=id_action) + + extra = """ + <dl> + <dt><a href="addauthorization?id_action=%s&reverse=1">Add new authorization</a></dt> + <dd>add an authorization.</dd> + <dt><a href="modifyauthorizations?id_action=%s&reverse=1">Modify authorizations</a></dt> + <dd>modify existing authorizations.</dd> + </dl> + """ % (id_action, id_action) + body = [output, extra] + + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show Action Details', + subtitle='show action details', + body=body) + + +def actiondetails(id_action=0): + """show details of given action. """ + + output = '' + + if id_action not in [0, '0']: + name_action = acca.acc_getActionName(id_action=id_action) + + output += '<p>action details:</p>' + output += tupletotable(header=['id', 'name', 'description', 'allowedkeywords', 'optional'], + tuple=[acca.acc_getActionDetails(id_action=id_action)]) + + roleshlp = acca.acc_getActionRoles(id_action=id_action) + if roleshlp: + roles = [] + for (id, name, dontcare) in roleshlp: + roles.append([id, name, + '<a href="simpleauthorization?id_role=%s&id_action=%s">show authorization details</a>' + % (id, id_action), + '<a href="simpleroleusers?id_role=%s">show connected users</a>' % (id, )]) + roletable = tupletotable(header=['id', 'name', '', ''], tuple=roles) + + output += '<p>roles connected to %s:</p>\n' % (headerstrong(action=name_action, query=0), ) + output += roletable + + else: + output += '<p>no roles connected to %s.</p>\n' % (headerstrong(action=name_action, query=0), ) + + else: + output += '<p>no details to show</p>' + + return output + + +def perform_addrole(req, name_role='', description='put description here.', confirm=0): + """form to add a new role with these values: + + name_role - name of the new role + + description - optional description of the role """ + + if not is_adminuser(req): return mustloginpage(req) + + name_role = cleanstring(name_role) + + title='Add Role' + subtitle = 'step 1 - give values to the requested fields' + + output = """ + <form action="addrole" method="POST"> + <span class="adminlabel">role name </span> + <input class="admin_wvar" type="text" name="name_role" value="%s" /> <br> + <span class="adminlabel">description </span> + <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> + <input class="adminbutton" type="submit" value="add role" /> + </form> + """ % (name_role, description) + + if name_role: + # description must be changed before submitting + subtitle = 'step 2 - confirm to add role' + internaldesc = '' + if description != 'put description here.': + internaldesc = description + + text = """ + add role with: <br>\n + name: <strong>%s</strong> <br>""" % (name_role, ) + if internaldesc: + text += 'description: <strong>%s</strong>?\n' % (description, ) + + output += createhiddenform(action="addrole", + text=text, + name_role=name_role, + description=description, + confirm=1) + + if confirm not in ["0", 0]: + result = acca.acc_addRole(name_role=name_role, + description=internaldesc) + + if result: + subtitle = 'step 3 - role added' + output += '<p>role added: </p>' + output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords'], + tuple=[result]) + else: + subtitle = 'step 3 - role could not be added' + output += '<p>sorry, could not add role, <br>role with the same name probably exists.</p>' + + extra = """ + <dl> + <dt><a href="addauthorization?id_role=%s">Add authorization</a></dt> + <dd>start adding new authorizations to this role.</dd> + </dl> """ % (acca.acc_getRoleId(name_role=name_role), ) + + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title=title, + body=body, + subtitle=subtitle) + + +def perform_deleterole(req, id_role="0", confirm=0): + """select a role and show all connected information, + + users - users that can access the role. + + actions - actions with possible authorizations.""" + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Delete role' + subtitle = 'step 1 - select role to delete' + name_role = id_role + + name_role = acca.acc_getRoleName(id_role=id_role) + output = createroleselect(id_role=id_role, + action="deleterole", + step=1, + roles=acca.acc_getAllRoles(), + button="delete role") + + if id_role != "0": + subtitle = 'step 2 - confirm delete of role' + + output += roledetails(id_role=id_role) + + output += createhiddenform(action="deleterole", + text='delete role <strong>%s</strong> and all connections?' % (name_role, ), + id_role=id_role, + confirm=1) + + if confirm: + res = acca.acc_deleteRole(id_role=id_role) + subtitle = 'step 3 - confirm role deleted' + if res: + output += "<p>confirm: role <strong>%s</strong> deleted.<br>" % (name_role, ) + output += "<strong>%s</strong> entries were removed.</p>" % (res, ) + else: + output += "<p>sorry, the role could not be deleted.</p>" + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showroledetails(req, id_role): + """show the details of a role.""" + + if not is_adminuser(req): return mustloginpage(req) + + if id_role not in [0, '0']: + output = roledetails(id_role=id_role) + + extra = """ + <dl> + <dt><a href="adduserrole?id_role=%s">Connect user</a></dt> + <dd>connect a user to the role.</dd> + <dt><a href="addauthorization?id_role=%s">Add new authorization</a></dt> + <dd>add an authorization.</dd> + <dt><a href="modifyauthorizations?id_role=%s">Modify authorizations</a></dt> + <dd>modify existing authorizations.</dd> + </dl> + """ % (id_role, id_role, id_role) + body = [output, extra] + + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show Role Details', + subtitle='show role details', + body=body) + + +def roledetails(id_role=0): + """create the string to show details about a role. """ + + name_role = acca.acc_getRoleName(id_role=id_role) + + usershlp = acca.acc_getRoleUsers(id_role) + users = [] + for (id, email, dontcare) in usershlp: + users.append([id, email, '<a href="showuserdetails?id_user=%s">show user details</a>' % (id, )]) + usertable = tupletotable(header=['id', 'email'], tuple=users) + + actionshlp = acca.acc_getRoleActions(id_role) + actions = [] + for (id, name, dontcare) in actionshlp: + actions.append([id, name, + '<a href="showactiondetails?id_role=%s&id_action=%s">show action details</a>' % (id_role, id), + '<a href="simpleauthorization?id_role=%s&id_action=%s">show authorization details</a>' % (id_role, id)]) + + actiontable = tupletotable(header=['id', 'name', '', ''], tuple=actions) + + # show role details + details = '<p>role details:</p>' + details += tupletotable(header=['id', 'name', 'description'], + tuple=[acca.acc_getRoleDetails(id_role=id_role)]) + + # show connected users + details += '<p>users connected to %s:</p>' % (headerstrong(role=name_role, query=0), ) + if users: + details += usertable + else: + details += '<p>no users connected.</p>' + # show connected authorizations + details += '<p>authorizations for %s:</p>' % (headerstrong(role=name_role, query=0), ) + if actions: + details += actiontable + else: + details += '<p>no authorizations connected</p>' + + return details + + + +def perform_adduserrole(req, id_role='0', email_user_pattern='', id_user='0', confirm=0): + """create connection between user and role. + + id_role - id of the role to add user to + + email_user_pattern - search for users using this pattern + + id_user - id of user to add to the role. """ + + if not is_adminuser(req): return mustloginpage(req) + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + title = 'Add user to role ' + subtitle = 'step 1 - select a role' + + output = createroleselect(id_role=id_role, + action="adduserrole", + step=1, + roles=acca.acc_getAllRoles()) + + # role is selected + if id_role != "0": + title += name_role + + subtitle = 'step 2 - search for users' + + # remove letters not allowed in an email + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">2. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output += createhiddenform(action="adduserrole", + text=text, + button="search for users", + id_role=id_role) + + # pattern is entered + if email_user_pattern: + # users with matching email-address + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + # users that are connected + users2 = run_sql("""SELECT DISTINCT u.id, u.email + FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user + WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s' + ORDER BY u.id """ % (id_role, email_user_pattern)) + + # no users that match the pattern + if not (users1 or users2): + output += 'no qualified users, try new search' + # show matching users + else: + subtitle = 'step 3 - select a user' + + users = [] + extrausers = [] + for (id, email) in users1: + if (id, email) not in users2: users.append([id,email,'']) + for (id, email) in users2: + extrausers.append([-id, email,'']) + + output += createuserselect(id_user=id_user, + action="adduserrole", + step=3, + users=users, + extrausers=extrausers, + button="add this user", + id_role=id_role, + email_user_pattern=email_user_pattern) + + try: id_user = int(id_user) + except ValueError: pass + # user selected already connected to role + if id_user < 0: + output += '<p>users in brackets are already attached to the role, try another one</p>' + # a user is selected + elif email_out: + subtitle = "step 4 - confirm to add user" + + output += createhiddenform(action="adduserrole", + text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role), + id_role=id_role, + email_user_pattern=email_user_pattern, + id_user=id_user, + confirm=1) + + # it is confirmed that this user should be added + if confirm: + # add user + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm user added' + output += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role) + else: + subtitle = 'step 5 - user could not be added' + output += '<p>sorry, but user could not be added.</p>' + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + </dl> + """ + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output, extra]) + + +def perform_addroleuser(req, email_user_pattern='', id_user='0', id_role='0', confirm=0): + """delete connection between role and user. + + id_role - id of role to disconnect + + id_user - id of user to disconnect. """ + + if not is_adminuser(req): return mustloginpage(req) + + email_out = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + title = 'Connect user to roles' + subtitle = 'step 1 - search for users' + + # clean email search string + email_user_pattern = cleanstring_email(email_user_pattern) + + text = ' <span class="adminlabel">1. search pattern </span>\n' + text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, ) + + output = createhiddenform(action='addroleuser', + text=text, + button='search for users', + id_role=id_role) + + if email_user_pattern: + subtitle = 'step 2 - select user' + + users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, )) + users = [] + for (id, email) in users1: users.append([id, email, '']) + + if not users: + output += '<p>no qualified users, try new search</p>' + else: + output += createuserselect(id_user=id_user, + action='addroleuser', + step=2, + users=users, + button='select user', + email_user_pattern=email_user_pattern) + + if int(id_user): + subtitle = 'step 3 - select role' + + # roles the user is connected to + role_ids = acca.acc_getUserRoles(id_user=id_user) + # all the roles + all_roles = acca.acc_getAllRoles() + + # sort the roles in connected and not connected roles + con_roles = [] + not_roles = [] + for (id, name, description) in all_roles: + if (id, ) in role_ids: con_roles.append([-id, name, description]) + else: not_roles.append([id, name, description]) + + # create roleselect + output += createroleselect(id_role=id_role, + action='addroleuser', + step=3, + roles=not_roles, + extraroles=con_roles, + button='add this role', + email_user_pattern=email_user_pattern, + id_user=id_user) + + if int(id_role) < 0: + output += '<p>roles in brackets are already connected to the user, try another one<p>' + elif int(id_role): + subtitle = 'step 4 - confirm to add role to user' + + output += createhiddenform(action='addroleuser', + text='add role <strong>%s</strong> to user <strong>%s</strong>?' % (name_role, email_out), + email_user_pattern=email_user_pattern, + id_user=id_user, + id_role=id_role, + confirm=1) + + if confirm: + # add role + result = acca.acc_addUserRole(id_user=id_user, id_role=id_role) + + if result and result[2]: + subtitle = 'step 5 - confirm role added' + output += '<p>confirm: role <strong>%s</strong> added to user <strong>%s</strong>.</p>' % (name_role, email_out) + else: + subtitle = 'step 5 - role could not be added' + output += '<p>sorry, but role could not be added</p>' + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + </dl> + """ + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output, extra]) + + +def perform_deleteuserrole(req, id_role='0', id_user='0', reverse=0, confirm=0): + """delete connection between role and user. + + id_role - id of role to disconnect + + id_user - id of user to disconnect. """ + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Delete user from role' + email_user = acca.acc_getUserEmail(id_user=id_user) + name_role = acca.acc_getRoleName(id_role=id_role) + + output = '' + + if reverse in [0, '0']: + subtitle='step 1 - select the role' + output += createroleselect(id_role=id_role, + action="deleteuserrole", + step=1, + roles=acca.acc_getAllRoles()) + + if id_role != "0": + subtitle = 'step 2 - select the user' + output += createuserselect(id_user=id_user, + action="deleteuserrole", + step=2, + users=acca.acc_getRoleUsers(id_role=id_role), + id_role=id_role) + + else: + # show only users connected to a role + users = run_sql("""SELECT DISTINCT(u.id), u.email, u.note + FROM user u LEFT JOIN user_accROLE ur + ON u.id = ur.id_user + WHERE ur.id_accROLE != 'NULL' AND u.email != '' + ORDER BY id """) + + has_roles = 1 + + # check if the user is connected to any roles + for (id, email, note) in users: + if str(id) == str(id_user): break + else: + subtitle = 'step 1 - user not connected' + output += '<p>no need to remove roles from this user,<br>user <strong>%s</strong> is not connected to any roles.</p>' % (email_user, ) + has_roles, id_user = 0, '0' # stop the rest of the output below... + + + if has_roles: + output += createuserselect(id_user=id_user, + action="deleteuserrole", + step=1, + users=users, + reverse=reverse) + + if id_user != "0": + subtitle = 'step 2 - select the user' + + role_ids = acca.acc_getUserRoles(id_user=id_user) + all_roles = run_sql("""SELECT id, name, description FROM accROLE ORDER BY id """) + roles = [] + for (id, name, desc) in all_roles: + if (id, ) in role_ids: roles.append([id, name, desc]) + + output += createroleselect(id_role=id_role, + action="deleteuserrole", + step=2, + roles=roles, + id_user=id_user, + reverse=reverse) + + if id_role != '0' and id_user != '0': + subtitle = 'step 3 - confirm delete of user' + output += createhiddenform(action="deleteuserrole", + text='<span class="adminlabel">3. confirm</span> delete user %s from %s?' % (headerstrong(user=id_user), headerstrong(role=id_role)), + id_role=id_role, + id_user=id_user, + reverse=reverse, + confirm=1) + + if confirm: + res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role) + if res: + subtitle = 'step 4 - confirm delete of user' + output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role) + else: + subtitle = 'step 4 - user could not be deleted' + output += 'sorry, but user could not be deleted<br>user is probably already deleted.' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_showuserdetails(req, id_user=0): + """show the details of a user. """ + + if not is_adminuser(req): return mustloginpage(req) + + if id_user not in [0, '0']: + output = userdetails(id_user=id_user) + + extra = """ + <dl> + <dt><a href="addroleuser?id_user=%s">Connect role</a></dt> + <dd>connect a role to the user.</dd> + </dl> + """ % (id_user, ) + + body = [output, extra] + else: + body = ['<p>no details to show</p>'] + + return index(req=req, + title='Show User Details', + subtitle='show user details', + body=body) + + +def userdetails(id_user=0): + """create the string to show details about a user. """ + + # find necessary details + email_user = acca.acc_getUserEmail(id_user=id_user) + + userroles = acca.acc_getUserRoles(id_user=id_user) + conn_roles = [] + + # find connected roles + for (id, name, desc) in acca.acc_getAllRoles(): + if (id, ) in userroles: + conn_roles.append([id, name, desc]) + conn_roles[-1].append('<a href="showroledetails?id_role=%s">show details</a>' % (id, )) + + if conn_roles: + # print details + details = '<p>roles connected to user <strong>%s</strong></p>' % (email_user, ) + details += tupletotable(header=['id', 'name', 'description', ''], tuple=conn_roles) + else: + details = '<p>no roles connected to user <strong>%s</strong>.</p>' % (email_user, ) + + return details + +def perform_addauthorization(req, id_role="0", id_action="0", optional=0, reverse="0", confirm=0, **keywords): + """ form to add new connection between user and role: + + id_role - role to connect + + id_action - action to connect + + reverse - role or action first? """ + + if not is_adminuser(req): return mustloginpage(req) + + # values that might get used + name_role = acca.acc_getRoleName(id_role=id_role) or id_role + name_action = acca.acc_getActionName(id_action=id_action) or id_action + optional = optional == 'on' and 1 or int(optional) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + # create the page according to which step the user is on + # role -> action -> arguments + if reverse in ["0", 0]: + subtitle = 'step 1 - select role' + output = createroleselect(id_role=id_role, + action="addauthorization", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + if id_role != "0": + subtitle = 'step 2 - select action' + rolacts = acca.acc_getRoleActions(id_role) + allhelp = acca.acc_getAllActions() + allacts = [] + for r in allhelp: + if r not in rolacts: allacts.append(r) + output += createactionselect(id_action=id_action, + action="addauthorization", + step=2, + actions=rolacts, + extraactions=allacts, + id_role=id_role, + reverse=reverse) + # action -> role -> arguments + else: + subtitle = 'step 1 - select action' + output = createactionselect(id_action=id_action, + action="addauthorization", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + if id_action != "0": + subtitle = 'step 2 - select role' + actroles = acca.acc_getActionRoles(id_action) + allhelp = acca.acc_getAllRoles() + allroles = [] + for r in allhelp: + if r not in actroles: allroles.append(r) + output += createroleselect(id_role=id_role, + action="addauthorization", + step=2, + roles=actroles, + extraroles=allroles, + id_action=id_action, + reverse=reverse) + + # ready for step 3 no matter which direction we took to get here + if id_action != "0" and id_role != "0": + subtitle = 'step 3 - enter values for the keywords\n' + + output += """ + <form action="addauthorization" method="POST"> + <input type="hidden" name="id_role" value="%s"> + <input type="hidden" name="id_action" value="%s"> + <input type="hidden" name="reverse" value="%s"> + """ % (id_role, id_action, reverse) + + res_keys = acca.acc_getActionKeywords(id_action=id_action) + + if not res_keys: + output += """ + <input type="hidden" name="confirm" value="1"> + create connection between %s? + <input class="adminbutton" type="submit" value="confirm"> + </form> + """ % (headerstrong(role=name_role, action=name_action, query=0), ) + + + else: + optionalargs = acca.acc_getActionIsOptional(id_action=id_action) + + output += '<span class="adminlabel">3. arguments</span><br>' + if optionalargs: + output += """ + <p> + <input type="checkbox" name="optional" %s /> + create connection without the need for arguments + </p> + """ % (optional and 'checked="checked"' or '', ) + + allkeys = 1 + for key in res_keys: + output += '<span class="adminlabel">%s </span>\n <input class="admin_wvar" type="text" name="%s"' % (key, key) + try: + val = keywords[key] = cleanstring_argumentvalue(keywords[key]) + if val: output += 'value="%s" ' % (val, ) + else: allkeys = 0 + except KeyError: allkeys = 0 + output += ' /> <br>\n' + output = output[:-5] + ' <input class="adminbutton" type="submit" value="create entry -->" />\n' + output += '</form>\n' + + # ask for confirmation + if allkeys not in ["0", 0] or optional: + keys = keywords.keys() + keys.reverse() + subtitle = 'step 4 - confirm add of authorization\n' + + text = """ + create connection between <br> + %s <br> + """ % (headerstrong(role=name_role, action=name_action, query=0), ) + + if optional: + text += 'withouth arguments' + keywords = {} + else: + for key in keys: + text += '<strong>%s</strong>: %s \n' % (key, keywords[key]) + + output += createhiddenform(action="addauthorization", + text=text, + id_role=id_role, + id_action=id_action, + reverse=reverse, + confirm=1, + optional=optional, + **keywords) + + # show existing authorizations + res = acca.acc_findPossibleActions(id_role, id_action) + output += '<p>existing authorizations:</p>' + if res: + output += tupletotable(header=res[0], tuple=res[1:]) + # shortcut to modifying authorizations + extra += """ + <dl> + <dt><a href="modifyauthorizations?id_role=%s&id_action=%s&reverse=%s">Modify authorizations</a></dt> + <dd>modify the existing authorizations.<dd> + </dl> """ % (id_role, id_action, reverse) + + else: output += '<p>no details to show</p>' + + + # user confirmed to add entries + if confirm: + subtitle = 'step 5 - confirm authorization added' + res1 = acca.acc_addRoleActionArguments_names(name_role=name_role, + name_action=name_action, + arglistid=-1, + optional=optional, + **keywords) + # newentries = '' + + if res1: + res2 = acca.acc_findPossibleActions(id_role, id_action) + arg = res1[0][3] # the arglistid + new = [res2[0]] + for row in res2[1:]: + if row[0] == arg: new.append(row) + + newauths = tupletotable(header=new[0], tuple=new[1:]) + newentries = tupletotable(header=['role id', 'action id', 'argument id', '#'], tuple=res1) + + st = 'style="vertical-align: top"' + output += """ + <p>new authorization and entries:</p> + <table><tr> + <td class="admintd" %s>%s</td> + <td class="admintd" %s>%s</td> + </tr></table> """ % (st, newauths, st, newentries) + + else: output += '<p>sorry, authorization could not be added,<br>it probably already exists</p>' + + # trying to put extra link on the right side + try: body = [output, extra] + except NameError: body = [output] + + return index(req=req, + title = 'Create entry for new authorization', + subtitle=subtitle, + body=body) + + +def perform_deleteroleaction(req, id_role="0", id_action="0", reverse=0, confirm=0): + """delete all connections between a role and an action. + + id_role - id of the role + + id_action - id of the action + + reverse - 0: ask for role first + 1: ask for action first""" + + if not is_adminuser(req): return mustloginpage(req) + + title = 'Remove action from role ' + + if reverse in ["0", 0]: + # select role -> action + subtitle = 'step 1 - select a role' + output = createroleselect(id_role=id_role, + action="deleteroleaction", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + + if id_role != "0": + rolacts = acca.acc_getRoleActions(id_role=id_role) + subtitle = 'step 2 - select the action' + output += createactionselect(id_action=id_action, + action="deleteroleaction", + step=2, + actions=rolacts, + reverse=reverse, + id_role=id_role, + button="remove connection and all authorizations") + else: + # select action -> role + subtitle = 'step 1 - select an action' + output = createactionselect(id_action=id_action, + action="deleteroleaction", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + + if id_action != "0": + actroles = acca.acc_getActionRoles(id_action=id_action) + subtitle = 'step 2 - select the role' + output += createroleselect(id_role=id_role, + action="deleteroleaction", + step=2, + roles=actroles, + button="remove connection and all authorizations", + id_action=id_action, + reverse=reverse) + + if id_action != "0" and id_role != "0": + subtitle = 'step 3 - confirm remove of action' + # ask for confirmation + + res = acca.acc_findPossibleActions(id_role, id_action) + + if res: + output += '<p>authorizations that also will be deleted:</p>' + output += tupletotable(header=res[0], tuple=res[1:]) + + output += createhiddenform(action="deleteroleaction", + text='remove action %s from %s' % (headerstrong(action=id_action), headerstrong(role=id_role)), + confirm=1, + id_role=id_role, + id_action=id_action, + reverse=reverse) + else: + output += 'no authorizations' + + # confirmation is given + if confirm: + subtitle = 'step 4 - confirm remove of action ' + res = acca.acc_deleteRoleAction(id_role=id_role, id_action=id_action) + if res: + output += '<p>confirm: removed %s from %s<br>' % (headerstrong(action=id_action), headerstrong(role=id_role)) + output += '<strong>%s</strong> entries were removed.</p>' % (res, ) + else: + output += '<p>sorry, no entries could be removed.</p>' + + return index(req=req, + title=title, + subtitle=subtitle, + body=[output]) + + +def perform_modifyauthorizations(req, id_role="0", id_action="0", reverse=0, confirm=0, errortext='', sel='', authids=[]): + """given ids of a role and an action, show all possible action combinations + with checkboxes and allow user to access other functions. + + id_role - id of the role + + id_action - id of the action + + reverse - 0: ask for role first + 1: ask for action first + + sel - which button and modification that is selected + + errortext - text to print when no connection exist between role and action + + authids - ids of checked checkboxes """ + + if not is_adminuser(req): return mustloginpage(req) + + name_role = acca.acc_getRoleName(id_role) + name_action = acca.acc_getActionName(id_action) + + extra = """ + <dl> + <dt><a href="addrole">Add new role</a></dt> + <dd>go here to add a new role.</dd> + <dt><a href="addaction">Add new action</a></dt> + <dd>go here to add a new action.</dd> + </dl> + """ + + if reverse in ["0", 0]: + # role -> action + subtitle = 'step 1 - select the role' + output = createroleselect(id_role=id_role, + action="modifyauthorizations", + step=1, + roles=acca.acc_getAllRoles(), + reverse=reverse) + + if id_role != "0": + rolacts = acca.acc_getRoleActions(id_role=id_role) + subtitle = 'step 2 - select the action' + output += createactionselect(id_action=id_action, + action="modifyauthorizations", + step=2, + actions=rolacts, + id_role=id_role, + reverse=reverse) + else: + # action -> role + subtitle = 'step 1 - select the action' + output = createactionselect(id_action=id_action, + action="modifyauthorizations", + step=1, + actions=acca.acc_getAllActions(), + reverse=reverse) + if id_action != "0": + actroles = acca.acc_getActionRoles(id_action=id_action) + subtitle = 'step 2 - select the role' + output += createroleselect(id_role=id_role, + action="modifyauthorizations", + step=2, + roles=actroles, + id_action=id_action, + reverse=reverse) + + if errortext: output += '<p>%s</p>' % (errortext, ) + + if id_role != "0" and id_action != "0": + # shortcut to modifying authorizations + extra += """ + <dl> + <dt><a href="addauthorization?id_role=%s&id_action=%s&reverse=%s">Add authorizations</a></dt> + <dd>Add and authorization to the existing.</dd> + </dl> """ % (id_role, id_action, reverse) + + # back to the main area + if type(authids) is not list: authids = [authids] + subtitle = 'step 3 - select groups and modification' + + # get info + res = acca.acc_findPossibleActions(id_role, id_action) + + # clean the authids + hiddenids = [] + if sel in ['delete selected']: + hiddenids = authids[:] + elif sel in ['split groups', 'merge groups']: + for authid in authids: + arghlp = res[int(authid)][0] + if authid not in hiddenids and arghlp not in [-1, '-1', 0, '0']: hiddenids.append(authid) + authids = hiddenids[:] + + if confirm: + # do selected modification and output with new authorizations + if sel == 'split groups': + res = splitgroups(id_role, id_action, authids) + elif sel == 'merge groups': + res = mergegroups(id_role, id_action, authids) + elif sel == 'delete selected': + res = deleteselected(id_role, id_action, authids) + authids = [] + res = acca.acc_findPossibleActions(id_role, id_action) + output += 'authorizations after <strong>%s</strong>.<br>\n' % (sel, ) + + elif sel and authids: + output += 'confirm choice of authorizations and modification.<br>\n' + else: + output += 'select authorizations and perform modification.<br>\n' + + if not res: + errortext='all connections deleted, try different ' + if reverse in ["0", 0]: + return perform_modifyauthorizations(req=req, id_role=id_role, errortext=errortext + 'action.') + else: + return perform_modifyauthorizations(req=req, id_action=id_action, reverse=reverse, errortext=errortext + 'role.') + + # display + output += modifyauthorizationsmenu(id_role, id_action, header=res[0], tuple=res[1:], checked=authids, reverse=reverse) + + if sel and authids: + # form with hidden authids + output += '<form action="%s" method="POST">\n' % ('modifyauthorizations', ) + + for hiddenid in hiddenids: + output += '<input type="hidden" name="authids" value="%s" />\n' % (hiddenid, ) + + # choose what to do + if sel == 'split groups': + output += '<p>split groups containing:</p>' + elif sel == 'merge groups': + output += '<p>merge groups containing:</p>' + elif sel == 'delete selected': + output += '<p>delete selected entries:</p>' + + extracolumn = '<input type="checkbox" name="confirm" value="1" />\n' + extracolumn += '<input class="adminbutton" type="submit" value="confirm" />\n' + + # show the entries here... + output += tupletotable_onlyselected(header=res[0], + tuple=res[1:], + selected=hiddenids, + extracolumn=extracolumn) + + output += '<input type="hidden" name="id_role" value="%s" />\n' % (id_role, ) + output += '<input type="hidden" name="id_action" value="%s" />\n' % (id_action, ) + output += '<input type="hidden" name="sel" value="%s" />\n' % (sel, ) + output += '<input type="hidden" name="reverse" value="%s" />\n' % (reverse, ) + output += '</form>' + + # tried to perform modification without something selected + elif sel and not authids and not confirm: + output += '<p>no valid groups selected</p>' + + # trying to put extra link on the right side + try: body = [output, extra] + except NameError: body = [output] + + # Display the page + return index(req=req, + title='Modify Authorizations', + subtitle=subtitle, + body=body) + + +def modifyauthorizationsmenu(id_role, id_action, tuple=[], header=[], checked=[], reverse=0): + """create table with header and checkboxes, used for multiple choice. + makes use of tupletotable to add the actual table + + id_role - selected role, hidden value in the form + + id_action - selected action, hidden value in the form + + tuple - all rows to be put in the table (with checkboxes) + + header - column headers, empty strings added at start and end + + checked - ids of rows to be checked """ + + if not tuple: + return 'no authorisations...' + + argnum = len(acca.acc_getActionKeywords(id_action=id_action)) + + tuple2 = [] + for t in tuple: tuple2.append(t[:]) + + tuple2 = addcheckboxes(datalist=tuple2, name='authids', startindex=1, checked=checked) + + hidden = '<input type="hidden" name="id_role" value="%s" /> \n' % (id_role, ) + hidden += '<input type="hidden" name="id_action" value="%s" /> \n' % (id_action, ) + hidden += '<input type="hidden" name="reverse" value="%s" /> \n' % (reverse, ) + + + button = '<input type="submit" class="adminbutton" value="delete selected" name="sel" />\n' + if argnum > 1: + button += '<input type="submit" class="adminbutton" value="split groups" name="sel" />\n' + button += '<input type="submit" class="adminbutton" value="merge groups" name="sel" />\n' + + hdrstr = '' + for h in [''] + header + ['']: hdrstr += ' <th class="adminheader">%s</th>\n' % (h, ) + if hdrstr: hdrstr = ' <tr>\n%s\n </tr>\n' % (hdrstr, ) + + output = '<form action="modifyauthorizations" method="POST">\n' + output += '<table class="admin_wvar_nomargin"> \n' + output += hdrstr + output += '<tr><td>%s</td></tr>\n' % (hidden, ) + + output += '<tr>' + for data in tuple2[0]: output += '<td class="admintd">%s</td>\n' % (data,) + output += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n' % (len(tuple2), button) + + output += '</tr>\n' + for row in tuple2[1:]: + output += ' <tr>\n' + for data in row: output += '<td class="admintd">%s</td>\n' % (data,) + output += ' </tr>\n' + + output += '</table>\n</form>\n' + + return output + + +def splitgroups(id_role=0, id_action=0, authids=[]): + """get all the old ones, gather up the arglistids find a list of + arglistidgroups to be split, unique get all actions in groups outside + of the old ones, (old arglistid is allowed). + + show them like in showselect. """ + + if not id_role or not id_action or not authids: + return 0 + + # find all the actions + datalist = acca.acc_findPossibleActions(id_role, id_action) + + if type(authids) is str: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + # argumentlistids of groups to be split + splitgrps = [] + for authid in authids: + hlp = datalist[authid][0] + if hlp not in splitgrps and authid in range(1,len(datalist)): + splitgrps.append(hlp) + + # split groups and return success or failure + result = 1 + for splitgroup in splitgrps: + result = 1 and acca.acc_splitArgumentGroup(id_role, id_action, splitgroup) + + return result + + +def mergegroups(id_role=0, id_action=0, authids=[]): + """get all the old ones, gather up the argauthids find a list + of arglistidgroups to be split, unique get all actions in groups + outside of the old ones, (old arglistid is allowed). + + show them like in showselect.""" + + if not id_role or not id_action or not authids: + return 0 + + datalist = acca.acc_findPossibleActions(id_role, id_action) + + if type(authids) is str: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + # argumentlistids of groups to be merged + mergegroups = [] + for authid in authids: + hlp = datalist[authid][0] + if hlp not in mergegroups and authid in range(1, len(datalist)): + mergegroups.append(hlp) + + # merge groups and return success or failure + if acca.acc_mergeArgumentGroups(id_role, id_action, mergegroups): + return 1 + else: + return 0 + + + +def deleteselected(id_role=0, id_action=0, authids=[]): + """delete checked authorizations/possible actions, ids in authids. + + id_role - role to delete from + + id_action - action to delete from + + authids - listids for which possible actions to delete.""" + + if not id_role or not id_action or not authids: + return 0 + + if type(authids) in [str, int]: authids = [authids] + for i in range(len(authids)): authids[i] = int(authids[i]) + + result = acca.acc_deletePossibleActions(id_role=id_role, + id_action=id_action, + authids=authids) + + return result + + +def addadminbox(header='', datalist=[], cls="admin_wvar"): + """used to create table around main data on a page, row based. + + header - header on top of the table + + datalist - list of the data to be added row by row + + cls - possible to select wich css-class to format the look of the table.""" + + try: per = str(100 // len(datalist)) + '%' + except ZeroDivisionError: per = 1 + + output = '<table class="%s" ' % (cls, ) + 'width="100%">\n' + output += """ + <thead> + <tr> + <th class="adminheaderleft" colspan="%s">%s</th> + </tr> + </thead> + <tbody> + """ % (len(datalist), header) + for row in [datalist]: + output += ' <tr>\n' + for data in row: + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % (per, data) + output += ' </tr>\n' + output += """ + </tbody> + </table> + """ + + return output + + +def addadminbox(header='', datalist=[], cls="admin_wvar"): + """used to create table around main data on a page, row based. + + header - header on top of the table + + datalist - list of the data to be added row by row + + cls - possible to select wich css-class to format the look of the table.""" + + if len(datalist) == 1: per = 100 + else: per = 75 + + output = '<table class="%s" ' % (cls, ) + 'width="100%">\n' + output += """ + <thead> + <tr> + <th class="adminheaderleft" colspan="%s">%s</th> + </tr> + </thead> + <tbody> + """ % (len(datalist), header) + + output += ' <tr>\n' + + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % (per, datalist[0]) + + if len(datalist) > 1: + output += """ + <td style="vertical-align: top; margin-top: 5px; width: %s;"> + %s + </td> + """ % ('25%', datalist[1]) + + output += ' </tr>\n' + + output += """ + </tbody> + </table> + """ + + return output + + +def adderrorbox(header='', datalist=[]): + """used to create table around main data on a page, row based""" + + try: perc= str(100 // len(datalist)) + '%' + except ZeroDivisionError: perc= 1 + + output = '<table class="errorbox" width="100%">' + output += '<thead><tr><th class="errorboxheader" colspan="%s">%s</th></tr></thead>' % (len(datalist), header) + output += '<tbody>' + for row in [datalist]: + output += '<tr>' + for data in row: + output += '<td style="vertical-align: top; margin-top: 5px; width: %s;">' % (perc, ) + output += data + output += '</td>' + output += '</tr>' + output += '</tbody></table>' + + return output + + +def tupletotable(header=[], tuple=[], start='', end='', extracolumn=''): + """create html table for a tuple. + + header - optional header for the columns + + tuple - create table of this + + start - text to be added in the beginning, most likely beginning of a form + + end - text to be added in the end, mot likely end of a form. + + extracolumn - mainly used to put in a button. """ + + tblstr = '' + for h in header + ['']: + tblstr += ' <th class="adminheader">%s</th>\n' % (h, ) + if tblstr: tblstr = ' <tr>\n%s\n </tr>\n' % (tblstr, ) + + tblstr = start + '<table class="admin_wvar_nomargin">\n' + tblstr + + # extra column + try: + extra = '<tr>' + row = tuple[0] + if type(row) not in [int, long, str, dict]: + for data in row: extra += '<td class="admintd">%s</td>\n' % (data,) + else: + extra += ' <td class="admintd">%s</td>\n' % (row, ) + extra += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n</tr>\n' % (len(tuple), extracolumn) + except IndexError: + extra = '' + tblstr += extra + + + for row in tuple[1:]: + tblstr += ' <tr>\n' + if type(row) not in [int, long, str, dict]: + for data in row: tblstr += '<td class="admintd">%s</td>\n' % (data,) + else: + tblstr += ' <td class="admintd">%s</td>\n' % (row, ) + tblstr += ' </tr> \n' + + tblstr += '</table> \n ' + tblstr += end + + return tblstr + + +def tupletotable_onlyselected(header=[], tuple=[], selected=[], start='', end='', extracolumn=''): + """create html table for a tuple. + + header - optional header for the columns + + tuple - create table of this + + selected - indexes of selected rows in the tuple + + start - put this in the beginning + + end - put this in the beginning + + extracolumn - mainly used to put in a button""" + + tuple2 = [] + + for index in selected: + tuple2.append(tuple[int(index)-1]) + + return tupletotable(header=header, + tuple=tuple2, + start=start, + end=end, + extracolumn=extracolumn) + + +def addcheckboxes(datalist=[], name='authids', startindex=1, checked=[]): + """adds checkboxes in front of the listdata. + + datalist - add checkboxes in front of this list + + name - name of all the checkboxes, values will be associated with this name + + startindex - usually 1 because of the header + + checked - values of checkboxes to be pre-checked """ + + if not type(checked) is list: checked = [checked] + for row in datalist: + if 1 or row[0] not in [-1, "-1", 0, "0"]: # always box, check another place + chkstr = str(startindex) in checked and 'checked="checked"' or '' + row.insert(0, '<input type="checkbox" name="%s" value="%s" %s />' % (name, startindex, chkstr)) + else: + row.insert(0, '') + startindex += 1 + return datalist + + +def headeritalic(**ids): + """transform keyword=value pairs to string with value in italics. + + **ids - a dictionary of pairs to create string from """ + + output = '' + value = '' + table = '' + + for key in ids.keys(): + if key in ['User', 'user']: + value, table = 'email', 'user' + elif key in ['Role', 'role']: + value, table = 'name', 'accROLE' + elif key in ['Action', 'action']: + value, table = 'name', 'accACTION' + else: + if output: output += ' and ' + output += ' %s <i>%s</i>' % (key, ids[key]) + continue + + res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key])) + + if res: + if output: output += ' and ' + output += ' %s <i>%s</i>' % (key, res[0][0]) + + return output + + +def headerstrong(query=1, **ids): + """transform keyword=value pairs to string with value in strong text. + + **ids - a dictionary of pairs to create string from + + query - 1 -> try to find names to ids of role, user and action. + 0 -> do not try to find names, use the value passed on """ + + output = '' + value = '' + table = '' + + for key in ids.keys(): + if key in ['User', 'user']: + value, table = 'email', 'user' + elif key in ['Role', 'role']: + value, table = 'name', 'accROLE' + elif key in ['Action', 'action']: + value, table = 'name', 'accACTION' + else: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, ids[key]) + continue + + if query: + res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key])) + if res: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, res[0][0]) + else: + if output: output += ' and ' + output += ' %s <strong>%s</strong>' % (key, ids[key]) + + return output + + +def startpage(): + """create the menu for the startpage""" + + body = """ + <table class="admin_wvar" width="100%s" summary=""> + <thead> + <tr> + <th class="adminheaderleft" colspan="2">Selection for Admin <i>%s</i></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> + <dl> + <dt><a href="webaccessadmin.py/rolearea">Role Area</a> + <dd>Main area to configure administration rights and authorization rules. + <dt><a href="webaccessadmin.py/actionarea">Action Area</a> + <dd>Configure administration rights with the actions as starting point. + <dt><a href="webaccessadmin.py/userarea">User Area</a> + <dd>Configure administration rights with the users as starting point. + <dt><a href="webaccessadmin.py/resetarea">Reset Area</a> + <dd>Reset roles, actions and authorizations. + </dl> + </td> + <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> </td> + </tr> + </tbody> + </table>""" % ('%', SUPERADMINROLE, '%', '%') + + return body + + +def perform_simpleauthorization(req, id_role=0, id_action=0): + """show a page with simple overview of authorizations between a + connected role and action. """ + + if not is_adminuser(req): return mustloginpage(req) + + res = acca.acc_findPossibleActions(id_role, id_action) + if res: + extra = createhiddenform(action='modifyauthorizations', + button='modify authorizations', + id_role=id_role, + id_action=id_action) + + output = '<p>authorizations for %s:</p>' % (headerstrong(action=id_action, role=id_role), ) + output += tupletotable(header=res[0], tuple=res[1:], extracolumn=extra) + else: + output = 'no details to show' + + return index(req=req, + title='Simple authorization details', + subtitle='simple authorization details', + body=[output]) + + +def perform_simpleroleusers(req, id_role=0): + """show a page with simple overview of a role and connected users. """ + + if not is_adminuser(req): return mustloginpage(req) + + res = acca.acc_getRoleUsers(id_role=id_role) + if res: + users = [] + for (id, name, dontcare) in res: users.append([id, name, '<a href="showuserdetails?id_user=%s">show user details</a>' + % (id, )]) + output = '<p>users connected to %s:</p>' % (headerstrong(role=id_role), ) + output += tupletotable(header=['id', 'name', ''], tuple=users) + else: + output = 'no users connected' + + return index(req=req, + title='Simple user details', + subtitle='simple user details', + body=[output]) + + +def createhiddenform(action="", text="", button="confirm", cnfrm='', **hidden): + """create select with hidden values and submit button + + action - name of the action to perform on submit + + text - additional text, can also be used to add non hidden input + + button - value/caption on the submit button + + cnfrm - if given, must check checkbox to confirm + + **hidden - dictionary with name=value pairs for hidden input """ + + output = '<form action="%s" method="POST">\n' % (action, ) + output += '<table>\n<tr><td>' + output += text + if cnfrm: + output += ' <input type="checkbox" name="confirm" value="1" />' + for key in hidden.keys(): + output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key]) + output += '</td><td style="vertical-align: bottom">' + output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, ) + output += '</td></tr></table>' + output += '</form>\n' + + return output + + +def createselect(id_input="0", label="", step=0, name="", + action="", list=[], extralist=[], + button="", **hidden): + """create form with select and hidden values + + id - the one to choose as selected if exists + + label - label shown to the left of the select + + name - the name of the select on which to reference it + + list - primary list to select from + + extralist - list of options to be put in paranthesis + + button - the value/text to be put on the button + + **hidden - name=value pairs to be put as hidden in the form. """ + + step = step and '%s. ' % step or '' + + output = '<form action="%s" method="POST">\n' % (action, ) + output += ' <span class="adminlabel">%s</span>\n' % (step + label, ) + output += ' <select name="%s" class="admin_w200">\n' % (name, ) + if not list and not extralist: + output += ' <option value="0">no %ss to select from</option>\n' % (label.split()[-1], ) + else: + output += ' <option value="0">%s</option>\n' % (label, ) + for (id, email, dontcare) in list: + if str(id) == id_input: output += ' <option value="%s" selected="selected">%s</option>\n' % (id, email) + else: output += ' <option value="%s">%s</option>\n' % (id, email) + for (id, email, dontcare) in extralist: + if str(id) == id_input: output += ' <option value="%s" selected="selected">(%s)</option>\n' % (id, email) + else: output += ' <option value="%s">(%s)</option>\n' % (id, email) + output += ' </select>\n' + for key in hidden.keys(): + output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key]) + output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, ) + output += '</form>\n' + + return output + + +def createactionselect(id_action="0", label="select action", step=0, name="id_action", + action="", actions=[], extraactions=[], + button="select action", **hidden): + """create a select for roles in a form. see createselect.""" + + return createselect(id_input=id_action, label=label, step=step, name=name, + action=action, list=actions, extralist=extraactions, + button=button, **hidden) + + +def createroleselect(id_role="0", label="select role", step=0, name="id_role", + action="", roles=[], extraroles=[], + button="select role", **hidden): + """create a select for roles in a form. see createselect.""" + + return createselect(id_input=id_role, label=label, step=step, name=name, + action=action, list=roles, extralist=extraroles, + button=button, **hidden) + + +def createuserselect(id_user="0", label="select user", step=0, name="id_user", + action="", users=[], extrausers=[], + button="select user", **hidden): + """create a select for users in a form.see createselect.""" + + return createselect(id_input=id_user, label=label, step=step, name=name, + action=action, list=users, extralist=extrausers, + button=button, **hidden) + + +def cleanstring(str='', comma=0): + """clean all the strings before submitting to access control admin. + remove characters not letter, number or underscore, also remove leading + underscores and numbers. return cleaned string. + + str - string to be cleaned + + comma - 1 -> allow the comma to divide multiple arguments + 0 -> wash commas as well """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_,]', '', str) + + # split string on commas + items = str.split(',') + str = '' + for item in items: + if not item: continue + if comma and str: str += ',' + # create valid variable names + str += re.sub(r'^([0-9_])*', '', item) + + return str + + +def cleanstring_argumentvalue(str=''): + """clean the value of an argument before submitting it. + allowed characters: a-z A-Z 0-9 _ and space + + str - string to be cleaned """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_ .]', '', str) + # trim leading and ending spaces + str = re.sub(r'^ *| *$', '', str) + + return str + + +def cleanstring_email(str=''): + """clean the string and return a valid email address. + + str - string to be cleaned """ + + # remove not allowed characters + str = re.sub(r'[^a-zA-Z0-9_.@]', '', str) + + return str + + +def check_email(str=''): + """control that submitted emails are correct. + this little check is not very good, but better than nothing. """ + + r = re.compile(r'(.)+\@(.)+\.(.)+') + return r.match(str) and 1 or 0