Author: Dirk Nordmann, 2002/12/16
Since version ZMS 1.3 the Zope user maintenance through Standard User Folder can be replaced by an own user maintenance per Simple User Folder.
For this the UserFolder is being replaced by the product SimpleUserFolder. In this way own user sources and roles can be easily defined. To implement an own user source, the type in the tabulator "Access" is to be put on user-defined.
In the following, a step-by-step description of the setup of an easy own user maintenance is exemplified by a case. The methods described below must be applied either in the Simple User Folder object itself or in another object from which the Simple User Folder can acquire them.
A user source provides information about all users (identification, password, roles) for the user maintenance. To create an own user source you will apply a DTML method userSource.
<!-- BO userSource (DTML Method) -->
<dtml-return "[
{'name':'admin1','password':'zms'},
{'name':'editor1','password':'zms'},
{'name':'editor2','password':'zms'},
{'name':'author1','password':'zms'},
{'name':'author2','password':'zms'},
{'name':'author3','password':'zms'},
{'name':'author4','password':'zms'},
{'name':'author5','password':'zms'},
{'name':'author6','password':'zms'},
]">
<!-- EO userSource (DTML Method) -->
The Script(Python) object addUser defines how users are assigned to a ZMS object. In this example, for each user a DTML document is applied.
## Script (Python) "addUser"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=name, password, roles
##title=
##
container.manage_addDTMLDocument(id=name,title='')
user = getattr(context,name)
# user.manage_addProperty('password',password,'string')
user.manage_addProperty('roles',roles,'lines')
return 'done'
The Script(Python) object editUser defines how to change user attributes. In the example the roles of one user only can be changed as attribute of the associated DTML document. All further attributes are provided by the external user source.
## Script (Python) "editUser" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters=name, password, roles ##title= ## user = getattr(container,name) # user.manage_changeProperties(password=password) user.manage_changeProperties(roles=roles) return 'done'
The Script(Python) object deleteUser implements the canceling of a user assignation. In the example the DTML document corresponding to the user is being deleted.
## Script (Python) "deleteUser" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters=name ##title= ## container.manage_delObjects(ids=[name]) return 'done'
You receive the names resp. IDs of all users assigned to a ZMS object through the Script(Python) object getUserNames.
## Script (Python) "getUserNames" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters= ##title= ## return container.objectIds(['DTML Document'])
You receive the attributes of a user assigned to a ZMS object by transferring the user´s name resp. ID to the Script(Python) object getUserDetails as parameter. You get a dictionary with all available attributes.
getUserDetails must always be added at last and with another name. For this you insert a Script(Python) object getUserDetails2 and then rename it in getUserDetails.
## Script (Python) "getUserDetails"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=name
##title=
##
userSource = []
dtml_method = getattr(container,'userSource',None)
if dtml_method is not None:
userSource = dtml_method()
user = getattr(container,name,None)
if user is not None:
for userSourceItem in userSource:
if userSourceItem['name'] == name:
return {
'password' : userSourceItem['password'],
'roles' : user.getProperty('roles'),
}
return None
The ZMS Management Interface for processing of users can be adapted to the needs of one´s own user maintenance. For this the DTML method manage_SimpleUserFolder is integrated. It has to manage independently the display as well as the processing (Insert, Change, Delete) of users.
<!-- BO manage_SimpleUserFolder (DTML Method) -->
<dtml-let user_list="_['userSource']">
<!---------// BO Roles //---------->
<dtml-call "REQUEST.set('tmp',[])">
<dtml-in "valid_roles()">
<dtml-let role="_['sequence-item']"
name="_.string.upper('ROLE_%s'%_.str(role))"
display="getLangStr(name,manage_lang)">
<dtml-if "(AUTHENTICATED_USER.has_permission('ZMS Administrator',getSelf())
and not role in ['Anonymous','Authenticated','Owner']) or
(AUTHENTICATED_USER.has_permission('ZMS Editor',getSelf())
and role in ['ZMSEditor','ZMSAuthor','ZMSSubscriber'])">
<dtml-if "display!=name">
<dtml-call "tmp.append((display,role))">
</dtml-if>
</dtml-if>
</dtml-let>
</dtml-in>
<dtml-call "tmp.sort()">
<dtml-call "REQUEST.set('select_roles',[])">
<dtml-in tmp>
<dtml-call "select_roles.append([_['sequence-item'],_['sequence-key']])">
</dtml-in>
<!---------// EO Roles //---------->
<!---------// BO Add/delete users //--------->
<dtml-if btn>
<dtml-if "btn==getLangStr('BTN_ADD',manage_lang)">
<dtml-with "getUserFolder()">
<dtml-in user_list mapping>
<dtml-if "name==new_name">
<dtml-call "addUser(new_name,password,new_roles)">
</dtml-if>
</dtml-in>
</dtml-with>
<div class="system-msg">
<dtml-var "getLangStr('MSG_INSERTED',manage_lang)
%('%s <i>%s</i>'%(getLangStr('ATTR_USER',manage_lang),new_name))">
(<dtml-var "getLangFmtDate(ZopeTime(),manage_lang)">)
</div>
<dtml-elif "btn==getLangStr('BTN_DELETE',manage_lang)">
<dtml-with "getUserFolder()">
<dtml-in "REQUEST.get('names',[])">
<dtml-call "deleteUser(_['sequence-item'])">
</dtml-in>
</dtml-with>
<div class="system-msg">
<dtml-var "getLangStr('MSG_DELETED',manage_lang)
%_.len(REQUEST.get('names',[]))">
(<dtml-var "getLangFmtDate(ZopeTime(),manage_lang)">)
</div>
</dtml-if>
<dtml-call "synchronizePublicAccess()">
</dtml-if>
<!---------// EO Add/delete users //--------->
<!------// BO Insert user form //------>
<dtml-call "REQUEST.set('user_names',getUserNames())">
<table cellspacing="1" cellpadding="0" border="0"
class="cmsBgColorStrong1">
<tr>
<td class="form-small" colspan="2">
<b>
<dtml-var "getLangStr('CAPTION_INSERT',manage_lang)
%getLangStr('ATTR_USER',manage_lang)">
</b>
</td>
</tr>
<tr valign="middle" class="cmsBgColorLight0">
<td class="form-small">
<b>
<dtml-var "getLangStr('ATTR_NAME',manage_lang)">
</b>
</td>
<td class="form-small">
<select class="form-small" name="new_name">
<dtml-in user_list mapping>
<dtml-unless "name in user_names">
<option value="<dtml-var name>">
<dtml-var name>
</option>
</dtml-unless>
</dtml-in>
</select>
</td>
</tr>
<tr valign="middle" class="cmsBgColorLight0">
<td class="form-small">
<b><dtml-var "getLangStr('ATTR_ROLES',manage_lang)"></b>
</td>
<td class="form-small">
<select class="form-small" name="new_roles:list" multiple="multiple">
<dtml-in select_roles>
<option value="<dtml-var "_['sequence-item'][0]">">
<dtml-var "_['sequence-item'][1]">
</option>
</dtml-in>
</select>
</td>
</tr>
<tr valign="middle" class="cmsBgColorLight0">
<td></td>
<td class="form-small">
<input class="form-small" type="submit" name="btn"
value="<dtml-var "getLangStr('BTN_ADD',manage_lang)">">
</td>
</tr>
</table>
<br>
<!------// EO Insert user form //------>
<!------// BO Display users //------>
<dtml-if user_names>
<table cellspacing="1" cellpadding="0" border="0"
class="cmsBgColorStrong1">
<tr valign="middle">
<td class="form-small" colspan="2">
<b>
<dtml-var "_.len(getUserNames())">
<dtml-var "getLangStr('ATTR_USER',manage_lang)">
</b>
</td>
</td>
</tr>
<dtml-in user_names>
<tr valign="middle"
<dtml-if sequence-odd>class="cmsBgColorLight0"
<dtml-else>class="cmsBgColorMedium0"</dtml-if>>
<td class="form-small" width="1%">
<input type="checkbox" name="names:list" value="<dtml-var sequence-item>">
</td>
<td class="form-small" width="83%">
<dtml-var sequence-item>
<dtml-let user_details="getUserDetails(_['sequence-item'])">
<dtml-if user_details>
<i>(
<dtml-in "user_details.get('roles','')">
<dtml-var sequence-item>
<dtml-unless sequence-end>, </dtml-unless>
</dtml-in>)
</i>
</dtml-if>
</dtml-let>
</td>
</tr>
<dtml-if sequence-end>
<tr>
<td class="form-small" colspan="2">
<input class="form-small" type="submit" name="btn"
value="<dtml-var "getLangStr('BTN_DELETE',manage_lang)">">
</td>
</tr>
</dtml-if>
</dtml-in>
</table>
<br>
</dtml-if>
<!------// EO Display users //------>
</dtml-let>
<!-- EO manage_SimpleUserFolder (DTML Method) -->