[Zope-dev] Suggestion: Blocking out Localroles?
Lennart Regebro
lennart@regebro.nu
Mon, 29 Oct 2001 23:26:58 +0100
This is a multi-part message in MIME format.
------=_NextPart_000_005D_01C160D1.347FB2E0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
I was going to put this up as a proposal, but I can't figure out how to add
a new proposal... :-) Then I checked out the new collector, and there is a
possibility to add a "feature" there too, so maybe this fits better there?
Anyway, heres the suggestion:
When developing a CM system in Zope a customer asked for a possibility to
"block out" a persons local role lower down in the hierarchy. That way a
person that has manager rights on a country-level could have these rights
removed on a regional level.
So, we implemented this as a HotFix, that seems to work fine. It also has a
user interface for local roles that is somewhat easier (in my opinion) to
use.
So what do you think? Is this stupid or good? Is it a "feature" or a
"proposal"?
I attached the files, you can put the __init__.py in any directory under
Products, and the dtml-files in a directory 'dtml' under that if you want to
try it out. I think it should work with a clean Zope installation (although
we haven't tested that for a couple of weeks).
------=_NextPart_000_005D_01C160D1.347FB2E0
Content-Type: application/octet-stream;
name="__init__.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="__init__.py"
print """Hotfixing: AccessControl: Extending Local Roles,
Lennart Regebro, 2001-10-04, version Easy Publisher 1.4.38"""
from AccessControl.Role import RoleManager
from AccessControl.User import BasicUser
import Globals
from Globals import DTMLFile
from App.Common import aq_base
from string import join
from AccessControl import ClassSecurityInfo
from urllib import quote
securityRoleManager =3D ClassSecurityInfo()
# Local roles support
# -------------------
#
# Local roles allow a user to be given extra roles in the context
# of a particular object (and its children). When a user is given
# extra roles in a particular object, an entry for that user is made
# in the __ac_local_roles__ dict containing the extra roles.
#__ac_local_roles__=3DNone
#TODO: New methods need to have "Change permissions" premissions defined =
for them
__ac_local_roles_white__ =3D {}
__ac_local_roles_black__ =3D {}
RoleManager.__ac_local_roles_white__ =3D __ac_local_roles_white__
RoleManager.__ac_local_roles_black__ =3D __ac_local_roles_black__
manage_listLocalRoles=3DDTMLFile('dtml/listLocalRoles', globals(),
management_view=3D'Security',
help_topic=3D'Security_Local-Roles.stx',
help_product=3D'OFSP')
RoleManager.manage_listLocalRoles =3D manage_listLocalRoles
manage_editLocalRoles=3DDTMLFile('dtml/editLocalRoles', globals(),
management_view=3D'Security',
=
help_topic=3D'Security_User-Local-Roles.stx',
help_product=3D'OFSP')
RoleManager.manage_editLocalRoles =3D manage_editLocalRoles
def has_local_roles(self):
dict=3Dself.__ac_local_roles__()
return len(dict)
RoleManager.has_local_roles =3D has_local_roles
def get_local_roles(self):
dict=3Dself.__ac_local_roles__()
keys=3Ddict.keys()
keys.sort()
info=3D[]
for key in keys:
value=3Dtuple(dict[key])
info.append((key, value))
return tuple(info)
RoleManager.get_local_roles =3D get_local_roles
def get_valid_userids(self):
item=3Dself
dict=3D{}
while 1:
if hasattr(aq_base(item), 'acl_users') and \
hasattr(item.acl_users, 'user_names'):
for name in item.acl_users.user_names():
dict[name]=3D1
if not hasattr(item, 'aq_parent'):
break
item=3Ditem.aq_parent
keys=3Ddict.keys()
keys.sort()
return tuple(keys)
RoleManager.get_valid_userids =3D get_valid_userids
securityRoleManager.declarePrivate('possible_contributers')
RoleManager.possible_contributers =3D get_valid_userids
securityRoleManager.declarePrivate('get_valid_userids_for_role')
def get_valid_userids_for_role(self, role):
item=3Dself
dict=3D{}
while 1:
if hasattr(aq_base(item), 'acl_users') and \
hasattr(item.acl_users, 'getUsers'):
for user in item.acl_users.getUsers():
if not dict.has_key(user.getId()) and =
user.has_role(role, object=3Dself):
dict[user.getId()]=3D1
if not hasattr(item, 'aq_parent'):
break
item=3Ditem.aq_parent
keys=3Ddict.keys()
keys.sort()
return tuple(keys)
RoleManager.get_valid_userids_for_role =3D get_valid_userids_for_role
def get_local_roles_for_userid(self, userid):
#PATCH: temporary patch code
if not callable(self.__ac_local_roles__): del =
self.__ac_local_roles__
dict=3Dself.__ac_local_roles__()
return tuple(dict.get(userid, []))
RoleManager.get_local_roles_for_userid =3D get_local_roles_for_userid
def manage_addLocalRoles(self, userid, roles, REQUEST=3DNone, =
RESPONSE=3DNone):
"""Set local roles for a user."""
if not roles:
raise ValueError, 'One or more roles must be given!'
dict=3Dself.__ac_local_roles__()
local_roles =3D list(dict.get(userid, []))
for r in roles:
if r not in local_roles:
local_roles.append(r)
dict[userid] =3D local_roles
self.setLocalRoles(dict)
if REQUEST and RESPONSE:
message=3D"Your changes have been saved."
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_addLocalRoles =3D manage_addLocalRoles
def manage_setLocalRoles(self, userid, roles, REQUEST=3DNone, =
RESPONSE=3DNone):
"""Set local roles for a user."""
if not roles:
raise ValueError, 'One or more roles must be given!'
dict=3Dself.__ac_local_roles__()
dict[userid]=3Droles
self.setLocalRoles(dict)
if REQUEST and RESPONSE:
message=3D"Your changes have been saved."
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_setLocalRoles =3D manage_setLocalRoles
def manage_delLocalRoles(self, userids, REQUEST=3DNone, =
RESPONSE=3DNone):
"""Remove all local roles for a user."""
dict=3Dself.__ac_local_roles__()
for userid in userids:
if dict.has_key(userid):
del dict[userid]
self.setLocalRoles(dict)
if REQUEST and RESPONSE:
message=3D"Users added as local authors."
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_delLocalRoles =3D manage_delLocalRoles
def __ac_local_roles__(self):
local_roles =3D self.__ac_local_roles_white__ or {}
local_roles =3D local_roles.copy()
black =3D self.__ac_local_roles_black__ or {}
blackusers =3D black.keys()
for user, roles in local_roles.items():
if user in blackusers:
local_roles[user] =3D filter(lambda r, br=3Dblack[user]: r =
not in br, roles)
return local_roles
RoleManager.__ac_local_roles__ =3D __ac_local_roles__
securityRoleManager.declarePrivate('setLocalRoles')
def setLocalRoles(self, local_roles_white):
self.__ac_local_roles_white__=3Dlocal_roles_white
RoleManager.setLocalRoles =3D setLocalRoles
securityRoleManager.declarePrivate('setLocalRolesBlack')
def setLocalRolesBlack(self, local_roles_black):
self.__ac_local_roles_black__=3Dlocal_roles_black
securityRoleManager.declarePrivate('getBlackRolesForUser')
def getBlackRolesForUser(self, user):
return self.__ac_local_roles_black__.get(user, ())
securityRoleManager.declarePrivate('getBlackList')
def getBlackList(self, user):
return self.__ac_local_roles_black__
RoleManager.setLocalRolesBlack =3D setLocalRolesBlack
RoleManager.getBlackRolesForUser =3D getBlackRolesForUser
RoleManager.getBlackList =3D getBlackList
# local_roles_with_hop
# {
# 'user1': {role1: hop0, role2: hop1, role3: hop0 },
# 'user2': {role1: hop1, role2: hop1, role3: hop1 },
# }
securityRoleManager.declarePrivate('get_local_roles_aq')
def get_local_roles_aq(self):
hop=3D-1
local_roles =3D {}
black_roles =3D {}
inner_obj =3D getattr(self, 'aq_inner', self)
while 1:
hop=3Dhop + 1
current_local_roles =3D =
getattr(inner_obj,'__ac_local_roles_white__',None)
current_black_roles =3D =
getattr(inner_obj,'__ac_local_roles_black__',None)
if current_black_roles is not None:
for user, roles in current_black_roles.items():
if not black_roles.has_key(user):
black_roles[user] =3D ()
black_roles[user] =3D black_roles[user] + roles
if current_local_roles is not None:
for user, roles in current_local_roles.items():
b_roles =3D black_roles.get(user, ())
for role in roles:
if not local_roles.has_key(user):
local_roles[user] =3D {}
if (role not in local_roles[user].keys()) and (role =
not in b_roles):
local_roles[user][role] =3D hop
inner =3D getattr(inner_obj, 'aq_inner', inner_obj)
parent =3D getattr(inner, 'aq_parent', None)
if parent is not None:
inner_obj =3D parent
continue
if hasattr(inner_obj, 'im_self'):
inner_obj=3Dinner_obj.im_self
inner_obj=3Dgetattr(inner_obj, 'aq_inner', inner_obj)
continue
break
return local_roles
RoleManager.get_local_roles_aq =3D get_local_roles_aq
securityRoleManager.declarePrivate('filter_acquired_roles_for_userid')
def filter_acquired_roles_for_userid(self, userid, =
local_roles_with_hop=3DNone):
if local_roles_with_hop is None: local_roles_with_hop=3D {}
if local_roles_with_hop.has_key(userid):
return map(lambda (role, hop): role,filter(lambda (role, hop): =
hop!=3D0, local_roles_with_hop[userid].items()))
return []
RoleManager.filter_acquired_roles_for_userid =3D =
filter_acquired_roles_for_userid
securityRoleManager.declarePrivate('getUserById')
def getUserById(self, userid):
item=3Dself
while 1:
if hasattr(aq_base(item), 'acl_users') and \
hasattr(item.acl_users, 'user_names'):
for name in item.acl_users.user_names():
if userid =3D=3D name:
#The User object needs to be in the context of the
#user folder that contains it.
return =
item.acl_users.getUser(userid).__of__(item.acl_users)
if not hasattr(item, 'aq_parent'):
break
item=3Ditem.aq_parent
return None
RoleManager.getUserById =3D getUserById
securityRoleManager.declareProtected('Change permissions', =
'manage_addLocalRolesForUsers')
def manage_addLocalRolesForUsers(self, userids=3DNone, roles=3DNone, =
REQUEST=3DNone, RESPONSE=3DNone):
"""Add Local Users"""
if roles is None: roles=3D[]
if userids is None: userids=3D[]
local_roles_white =3D self.__ac_local_roles_white__
for user in userids:
users_white_roles =3D list(local_roles_white[user])
for role in roles:
if role not in users_white_roles: =
users_white_roles.append(role)
local_roles_white[user] =3D tuple(users_white_roles)
self.setLocalRoles(local_roles_white)
if REQUEST and RESPONSE:
message=3D"Lennart has been blacklisted as Author."
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_addLocalRolesForUsers =3D =
manage_addLocalRolesForUsers
securityRoleManager.declareProtected('Change permissions', =
'manage_delLocalRolesForUsers')
def manage_delLocalRolesForUsers(self, userids=3DNone, roles=3DNone, =
REQUEST=3DNone, RESPONSE=3DNone):
"""Delete Local Users"""
if roles is None: roles=3D[]
if userids is None: userids=3D[]
local_roles_white =3D self.__ac_local_roles_white__
for user in userids:
users_white_roles =3D list(local_roles_white[user])
for role in roles:
if role in users_white_roles: users_white_roles.remove(role)
local_roles_white[user] =3D tuple(users_white_roles)
self.setLocalRoles(local_roles_white)
if REQUEST and RESPONSE:
message=3D"[%s] has been given the role(s): [%s]." % =
(join(userids, ', '),join(roles, ', '))
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_delLocalRolesForUsers =3D =
manage_delLocalRolesForUsers
securityRoleManager.declareProtected('Change permissions', =
'manage_disableLocalRolesForUsers')
def manage_disableLocalRolesForUsers(self, userids=3DNone, roles=3DNone, =
REQUEST=3DNone, RESPONSE=3DNone):
"""Disable users from Local Role Access"""
if roles is None: roles=3D[]
if userids is None: userids=3D[]
local_roles_black =3D self.__ac_local_roles_black__
for user in userids:
users_black_roles =3D list(local_roles_black.get(user,()))
for role in roles:
if role not in users_black_roles: =
users_black_roles.append(role)
local_roles_black[user] =3D tuple(users_black_roles)
self.setLocalRolesBlack(local_roles_black)
if REQUEST and RESPONSE:
message=3D"[%s] has been removed as local role(s): [%s]." % =
(join(userids, ', '),join(roles, ', '))
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_disableLocalRolesForUsers =3D =
manage_disableLocalRolesForUsers
securityRoleManager.declareProtected('Change permissions', =
'manage_enableLocalRolesForUsers')
def manage_enableLocalRolesForUsers(self, userids=3DNone, roles=3DNone, =
REQUEST=3DNone, RESPONSE=3DNone):
"""Enable disabled users from Local Role Access"""
if roles is None: roles=3D[]
if userids is None: userids=3D[]
local_roles_black =3D self.__ac_local_roles_black__
for user in userids:
users_black_roles =3D list(local_roles_black.get(user,()))
for role in roles:
if role in users_black_roles: users_black_roles.remove(role)
local_roles_black[user] =3D tuple(users_black_roles)
self.setLocalRolesBlack(local_roles_black)
if REQUEST and RESPONSE:
message=3D"%s has been enabled as %s." % (join(userids,', =
'),join(roles,', '))
=
RESPONSE.redirect('%s/manage_listLocalRoles?manage_tabs_message=3D%s' % =
(REQUEST.URL1, quote(message)))
RoleManager.manage_enableLocalRolesForUsers =3D =
manage_enableLocalRolesForUsers
RoleManager.security =3D securityRoleManager
Globals.InitializeClass(RoleManager)
# =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
# PATCH OF AccessControl.User.py
securityBasicUser =3D ClassSecurityInfo()
def getRolesInContext(self, object):
"""
Return the list of roles assigned to the user,
including local roles assigned in context of
the passed in object.
"""
name=3Dself.getUserName()
roles=3Dself.getRoles()
black_roles =3D ()
inner_obj =3D getattr(object, 'aq_inner', object)
while 1:
current_local_roles =3D =
getattr(inner_obj,'__ac_local_roles_white__',None)
current_black_roles =3D =
getattr(inner_obj,'__ac_local_roles_black__',None)
if current_black_roles is not None:
black_roles =3D black_roles + current_black_roles.get(name, =
())
if current_local_roles is not None:
for local_role in current_local_roles.get(name, ()):
if (local_role not in roles) and (local_role not in =
black_roles):
roles =3D roles + (local_role,)
inner =3D getattr(inner_obj, 'aq_inner', inner_obj)
parent =3D getattr(inner, 'aq_parent', None)
if parent is not None:
inner_obj =3D parent
continue
if hasattr(inner_obj, 'im_self'):
inner_obj=3Dinner_obj.im_self
inner_obj=3Dgetattr(inner_obj, 'aq_inner', inner_obj)
continue
break
return roles
BasicUser.getRolesInContext =3D getRolesInContext
def allowed(self, object, object_roles=3DNone):
"""Check whether the user has access to object. The user must
have one of the roles in object_roles to allow access."""
# Short-circuit the common case of anonymous access.
if object_roles is None or 'Anonymous' in object_roles:
return 1
# Check for ancient role data up front, convert if found.
# This should almost never happen, and should probably be
# deprecated at some point.
if 'Shared' in object_roles:
object_roles =3D self._shared_roles(object)
if object_roles is None or 'Anonymous' in object_roles:
return 1
# Check for a role match with the normal roles given to
# the user, then with local roles only if necessary. We
# want to avoid as much overhead as possible.
user_roles =3D self.getRoles()
for role in object_roles:
if role in user_roles:
if self._check_context(object):
return 1
return None
# Still have not found a match, so check local roles. We do
# this manually rather than call getRolesInContext so that
# we can incur only the overhead required to find a match.
inner_obj =3D getattr(object, 'aq_inner', object)
name=3Dself.getUserName()
black_roles =3D ()
while 1:
current_local_roles =3D =
getattr(inner_obj,'__ac_local_roles_white__',None)
current_black_roles =3D =
getattr(inner_obj,'__ac_local_roles_black__',None)
if current_black_roles is not None:
black_roles =3D black_roles + current_black_roles.get(name, =
())
if current_local_roles is not None:
local_roles =3D current_local_roles.get(name, [])
for role in object_roles:
if role in local_roles and role not in black_roles:
if self._check_context(object):
return 1
return None
inner =3D getattr(inner_obj, 'aq_inner', inner_obj)
parent =3D getattr(inner, 'aq_parent', None)
if parent is not None:
inner_obj =3D parent
continue
if hasattr(inner_obj, 'im_self'):
inner_obj=3Dinner_obj.im_self
inner_obj=3Dgetattr(inner_obj, 'aq_inner', inner_obj)
continue
break
return None
BasicUser.allowed =3D allowed
BasicUser.security =3D securityBasicUser
Globals.InitializeClass(BasicUser)
------=_NextPart_000_005D_01C160D1.347FB2E0
Content-Type: application/octet-stream;
name="listLocalRoles.dtml"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="listLocalRoles.dtml"
<dtml-var manage_page_header>
<dtml-with "_(management_view=3D'LocalRoles')">
<dtml-if manage_tabs><dtml-var manage_tabs></dtml-if>
</dtml-with>
<h1 class=3D"strong-header">Manage Local Roles</h1>
<p class=3D"form-help">
Local roles allow you to give particular users extra roles in the =
context
of this object, in addition to the roles they already have.
</p>
<dtml-let local_roles_aq=3D"get_local_roles_aq()">
<dtml-if local_roles_aq>
<p class=3D"form-help">
The following users have been given local roles. To modify the local =
roles
given to a particular user, click on the name of the user.
</p>
<form action=3D"&dtml-URL1;" method=3D"POST">
<table cellspacing=3D"0" cellpadding=3D"0" border=3D"0">
<tr class=3D"list-header">
<td align=3D"left" valign=3D"middle"></td>
<td align=3D"left" valign=3D"middle" class=3D"form-label" =
style=3D"padding:2px 20px 2px 4px">User</td>
<td align=3D"left" valign=3D"middle" class=3D"form-label" =
style=3D"padding:2px 20px 2px 4px">Global Roles</td>
<td align=3D"left" valign=3D"middle" style=3D"padding:2px 20px 2px =
4px"><span class=3D"form-label">Local Roles </span></td>
<td align=3D"left" valign=3D"middle" class=3D"form-label" =
style=3D"padding:2px 20px 2px 4px">Effective Roles</td>
</tr>
<tr><td colspan=3D"5"></td></tr>
<dtml-in "local_roles_aq.items()">
<tr>
<td align=3D"left" valign=3D"top">
<input type=3D"checkbox" name=3D"userids:list" value=3D"<dtml-var =
sequence-key html_quote>" />
</td>
<td align=3D"left" valign=3D"top" class=3D"form-text" =
style=3D"padding:2px 20px 2px 4px">
<a href=3D"manage_editLocalRoles?userid=3D<dtml-var sequence-key =
fmt=3D"url-quote">"><dtml-var sequence-key></a>
</div>
</td>
<td align=3D"left" valign=3D"top" class=3D"form-text" =
style=3D"padding:2px 20px 2px 4px">
<dtml-in "getUserById(_['sequence-key']).getRoles()">
<dtml-var sequence-item><dtml-unless sequence-end>, =
</dtml-unless>
</dtml-in>
</td>
<td align=3D"left" valign=3D"top" class=3D"form-text" =
style=3D"padding:2px 20px 2px 4px">
<dtml-let locals=3D"get_local_roles_for_userid(_['sequence-key'])" =
aq_locals=3D"filter_acquired_roles_for_userid(_['sequence-key'], =
local_roles_aq)" blacks=3D"getBlackRolesForUser(_['sequence-key'])">
<dtml-in locals>
<dtml-var sequence-item><dtml-unless "not aq_locals and not =
blacks and _['sequence-end']">, </dtml-unless>
</dtml-in>
<span style=3D"color:#000099">
<dtml-in aq_locals>
<dtml-var sequence-item>++<dtml-unless "not blacks and =
_['sequence-end']">, </dtml-unless>
</dtml-in>
</span>
<span style=3D"color:#990000">
<dtml-in blacks>
<dtml-var sequence-item>--<dtml-unless sequence-end>, =
</dtml-unless>
</dtml-in>
</span>
</dtml-let>
</td>
<td align=3D"left" valign=3D"top" class=3D"form-text" =
style=3D"padding:2px 20px 2px 4px">
<dtml-in "getUserById(_['sequence-key']).getRolesInContext(this())">
<dtml-var sequence-item><dtml-unless sequence-end>, =
</dtml-unless>
</dtml-in>
</td>
</tr>
</dtml-in>
<tr><td colspan=3D"5" height=3D"6"></td></tr>
<tr>
<td> </td>
<td colspan=3D"4" class=3D"form-text"><em>
Symbols: LocalRole, <span style=3D"color:#000099">Acquired++</span>, =
and <span style=3D"color:#990000">Disabled--</span><br>
(Disabling only applies to localy defined roles or acquired local =
roles.)</em>
</td>
</tr>
<tr><td colspan=3D"5" height=3D"8"></td></tr>
<tr>
<td align=3D"left" valign=3D"top">
</td>
<td align=3D"left" valign=3D"top" colspan=3D"4" =
class=3D"form-element">
<input class=3D"form-element" type=3D"submit" =
name=3D"manage_addLocalRolesForUsers:method" value=3D"Add Local Role(s)" =
/>
<input class=3D"form-element" type=3D"submit" =
name=3D"manage_delLocalRolesForUsers:method" value=3D"Remove Local =
Role(s)" />
<input class=3D"form-element" type=3D"submit" =
name=3D"manage_disableLocalRolesForUsers:method" value=3D"Disable Local =
Role(s)" />
<input class=3D"form-element" type=3D"submit" =
name=3D"manage_enableLocalRolesForUsers:method" value=3D"Enable Local =
Role(s)" />
<br>
<select name=3D"roles:list" size=3D"5" multiple>
<dtml-in valid_roles>
<dtml-if "_vars['sequence-item'] not in ('Anonymous', =
'Shared')">
<option value=3D"<dtml-var sequence-item =
html_quote>"><dtml-var sequence-item></option>
</dtml-if>
</dtml-in>
</select>
</td>
</tr>
</table>
</form>
</dtml-if>
</dtml-let>
<h2 class=3D"form-title">Add a Local User</h2>
<p>
To give a user extra roles when accessing this object (and its =
children),
select a user from the <em>User</em> list below, select the extra
roles that should be given to that user from the <em>Roles</em> list.
</p>
<form action=3D"manage_setLocalRoles" method=3D"POST">
<table cellpadding=3D"2" cellspacing=3D"0" border=3D"0">
<tr>
<td align=3D"left" valign=3D"top">
<div class=3D"form-label">
User
</div>
</td>
<td align=3D"left" valign=3D"top">
<div class=3D"form-label">
Roles
</div>
</td>
</tr>
<tr>
<td align=3D"left" valign=3D"top">
<div class=3D"form-element">
<select name=3D"userid" size=3D"5">
<dtml-in get_valid_userids>
<option value=3D"<dtml-var sequence-item html_quote>"><dtml-var
sequence-item></option>
</dtml-in>
</select>
</div>
</td>
<td align=3D"left" valign=3D"top">
<div class=3D"form-element">
<select name=3D"roles:list" size=3D"5" multiple>
<dtml-in valid_roles><dtml-if
"_vars['sequence-item'] not in ('Anonymous', 'Shared')">
<option value=3D"<dtml-var sequence-item html_quote>"><dtml-var
sequence-item></option>
</dtml-if>
</dtml-in>
</select>
</div>
</td>
</tr>
<tr>
<td align=3D"left" valign=3D"top">
<div class=3D"form-element">
<input class=3D"form-element" type=3D"submit" name=3D"submit" =
value=3D" Add " />
</div>
</td>
<td></td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
------=_NextPart_000_005D_01C160D1.347FB2E0
Content-Type: application/octet-stream;
name="editLocalRoles.dtml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="editLocalRoles.dtml"
<dtml-var manage_page_header>
<dtml-with "_(management_view='Security')">
<dtml-if manage_tabs><dtml-var manage_tabs></dtml-if>
</dtml-with>
<p class="form-help">
Local roles allow you to give particular users extra roles in the
context of this object, in addition to the roles they already have.
</p>
<p class="form-help">
To change the local roles for this user, select the extra roles this
user should have in the context of this object and click the <em>
Save Changes</em> button.
</p>
<form action="manage_setLocalRoles" method="post">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">User</div>
</td>
<td align="left" valign="top">
<div class="form-label">Roles</div>
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-text"><dtml-var userid></div>
</td>
<td align="left" valign="top">
<div class="form-element">
<input type="hidden" name="userid" value="<dtml-var userid html_quote>">
<dtml-with "_(user_roles=get_local_roles_for_userid(userid))">
<select name="roles:list" size="5" multiple>
<dtml-in valid_roles><dtml-if
"_vars['sequence-item'] not in ('Anonymous', 'Shared')">
<option value="<dtml-var sequence-item html_quote>"<dtml-if
"_['sequence-item'] in user_roles"> selected</dtml-if>><dtml-var
sequence-item>
</dtml-if>
</dtml-in>
</select>
</dtml-with>
</div>
</td>
</tr>
<tr>
<td align="left" valign="top" colspan="2">
<div class="form-element">
<input class="form-element" type="submit" value="Save Changes" />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
------=_NextPart_000_005D_01C160D1.347FB2E0--