Back to index

plone3  3.1.7
IUserFolder.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 ## GroupUserFolder
00003 ## Copyright (C)2006 Ingeniweb
00004 
00005 ## This program is free software; you can redistribute it and/or modify
00006 ## it under the terms of the GNU General Public License as published by
00007 ## the Free Software Foundation; either version 2 of the License, or
00008 ## (at your option) any later version.
00009 
00010 ## This program is distributed in the hope that it will be useful,
00011 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ## GNU General Public License for more details.
00014 
00015 ## You should have received a copy of the GNU General Public License
00016 ## along with this program; see the file COPYING. If not, write to the
00017 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 """
00019 VOCABULARY:
00020 
00021   - [Pure] User: A user is a user atom who can log itself on, and
00022     have additional properties such as domains and password.
00023 
00024   - Group: A group is a user atom other atoms can belong to.
00025 
00026   - User atom: Abstract representation of either a User or
00027     a Group.
00028 
00029   - Member (of a group): User atom inside a group.
00030 
00031   - Name (of an atom): For a user, the name can be set by
00032     the underlying user folder but usually id == name.
00033     For a group, its id is prefixed, but its name is NOT prefixed by 'group_'.
00034     For method taking a name instead of an id (eg. getUserByName()),
00035     if a user and a group have the same name,
00036     the USER will have precedence over the group.
00037 """
00038 __version__ = "$Revision:  $"
00039 # $Source:  $
00040 # $Id: IUserFolder.py 30098 2006-09-08 12:35:01Z encolpe $
00041 __docformat__ = 'restructuredtext'
00042 
00043 from Interface import Attribute
00044 try:
00045     from Interface import Interface
00046 except ImportError:
00047     # for Zope versions before 2.6.0
00048     from Interface import Base as Interface
00049 
00050 
00051 
00052 class IUserFolder(Interface):
00053 
00054     #                                                   #
00055     #           Regular Zope UserFolder API             #
00056     #                                                   #
00057 
00058     # User atom access
00059     
00060     def getUserNames():
00061         """
00062         Return a list of all possible user atom names in the system.
00063         Groups will be returned WITHOUT their prefix by this method.
00064         So, there might be a collision between a user name and a group name.
00065         [NOTA: This method is time-expensive !]
00066         """
00067 
00068     def getUserIds():
00069         """
00070         Return a list of all possible user atom ids in the system.
00071         WARNING: Please see the id Vs. name consideration at the
00072         top of this document. So, groups will be returned
00073         WITH their prefix by this method
00074         [NOTA: This method is time-expensive !]
00075         """
00076         
00077     def getUser(name):
00078         """Return the named user atom object or None
00079         NOTA: If no user can be found, we try to append a group prefix
00080         and fetch the user again before returning 'None'. This will ensure
00081         backward compatibility. So in fact, both group id and group name can be
00082         specified to this method.
00083         """
00084 
00085     def getUsers():
00086         """Return a list of user atom objects in the users cache.
00087         In case of some UF implementations, the returned object may only be a subset
00088         of all possible users.
00089         In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()).
00090         With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will
00091         return only cached user objects instead of fetching all possible users.
00092         So this method won't be very time-expensive, but won't be accurate !
00093         """
00094 
00095     def getUserById(id, default):
00096         """Return the user atom corresponding to the given id.
00097         If default is provided, return default if no user found, else return None.
00098         """
00099 
00100     def getUserByName(name, default):
00101         """Same as getUserById() but works with a name instead of an id.
00102         If default is provided, return default if no user found, else return None.
00103         [NOTA: Theorically, the id is a handle, while the name is the actual login name.
00104         But difference between a user id and a user name is unsignificant in
00105         all current User Folder implementations... except for GROUPS.]        
00106         """
00107 
00108     def hasUsers():
00109         """
00110         From Zope 2.7's User.py:
00111         This is not a formal API method: it is used only to provide
00112         a way for the quickstart page to determine if the default user
00113         folder contains any users to provide instructions on how to
00114         add a user for newbies.  Using getUserNames or getUsers would have
00115         posed a denial of service risk.
00116         In GRUF, this method always return 1."""
00117     
00118 
00119     # Search interface for users; they won't return groups in any case.
00120 
00121     def searchUsersByName(search_term):
00122         """Return user ids which match the specified search_term.
00123         If search_term is an empty string, behaviour depends on the underlying user folder:
00124         it may return all users, return only cached users (for LDAPUF) or return no users.
00125         """
00126 
00127     def searchUsersById(search_term):
00128         """Return users whose id match the specified search_term.
00129         If search_term is an empty string, behaviour depends on the underlying user folder:
00130         it may return all users, return only cached users (for LDAPUF) or return no users.
00131         """
00132         
00133     def searchUsersByAttribute(attribute, search_term):
00134         """Return user ids whose 'attribute' match the specified search_term.
00135         If search_term is an empty string, behaviour depends on the underlying user folder:
00136         it may return all users, return only cached users (for LDAPUF) or return no users.
00137         This will return all users whose name contains search_term (whaterver its case).
00138         THIS METHOD MAY BE VERY EXPENSIVE ON USER FOLDER KINDS WHICH DO NOT PROVIDE A
00139         SEARCHING METHOD (ie. every UF kind except LDAPUF).
00140         'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF.
00141         [NOTA: This method is time-expensive !]
00142         """
00143 
00144     # Search interface for groups;
00145 
00146     def searchGroupsByName(search_term):
00147         """Return group ids which match the specified search_term.
00148         If search_term is an empty string, behaviour depends on the underlying group folder:
00149         it may return all groups, return only cached groups (for LDAPUF) or return no groups.
00150         """
00151 
00152     def searchGroupsById(search_term):
00153         """Return groups whose id match the specified search_term.
00154         If search_term is an empty string, behaviour depends on the underlying group folder:
00155         it may return all groups, return only cached groups (for LDAPUF) or return no groups.
00156         """
00157         
00158     def searchGroupsByAttribute(attribute, search_term):
00159         """Return group ids whose 'attribute' match the specified search_term.
00160         If search_term is an empty string, behaviour depends on the underlying group folder:
00161         it may return all groups, return only cached groups (for LDAPUF) or return no groups.
00162         This will return all groups whose name contains search_term (whaterver its case).
00163         THIS METHOD MAY BE VERY EXPENSIVE ON GROUP FOLDER KINDS WHICH DO NOT PROVIDE A
00164         SEARCHING METHOD (ie. every UF kind except LDAPUF).
00165         'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF.
00166         [NOTA: This method is time-expensive !]
00167         """
00168 
00169 
00170     # User access
00171 
00172     def getPureUserNames():
00173         """Same as getUserNames() but without groups
00174         """
00175 
00176     def getPureUserIds():
00177         """Same as getUserIds() but without groups
00178         """
00179 
00180     def getPureUsers():
00181         """Same as getUsers() but without groups.
00182         """
00183 
00184     def getPureUser(id):
00185         """Same as getUser() but forces returning a user and not a group
00186         """
00187         
00188     # Group access
00189 
00190     def getGroupNames():
00191         """Same as getUserNames() but without pure users.
00192         """
00193 
00194     def getGroupIds():
00195         """Same as getUserIds() but without pure users.
00196         """
00197 
00198     def getGroups():
00199         """Same as getUsers() but without pure users.
00200         In case of some UF implementations, the returned object may only be a subset
00201         of all possible users.
00202         In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()).
00203         With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will
00204         return only cached user objects instead of fetching all possible users.
00205         So this method won't be very time-expensive, but won't be accurate !
00206         """
00207 
00208     def getGroup(name):
00209         """Return the named group object or None. As usual, 'id' is prefixed.
00210         """
00211 
00212     def getGroupById(id):
00213         """Same as getUserById(id) but forces returning a group.
00214         """
00215 
00216     def getGroupByName(name):
00217         """Same as getUserByName(name) but forces returning a group.
00218         The specified name MUST NOT be prefixed !
00219         """
00220     
00221 
00222     # Mutators
00223 
00224     def userFolderAddUser(name, password, roles, domains, groups, **kw):
00225         """API method for creating a new user object. Note that not all
00226         user folder implementations support dynamic creation of user
00227         objects.
00228         Groups can be specified by name or by id (preferabily by name)."""
00229 
00230     def userFolderEditUser(name, password, roles, domains, groups, **kw):
00231         """API method for changing user object attributes. Note that not
00232         all user folder implementations support changing of user object
00233         attributes.
00234         Groups can be specified by name or by id (preferabily by name)."""
00235 
00236     def userFolderUpdateUser(name, password, roles, domains, groups, **kw):
00237         """Same as userFolderEditUser, but with all arguments except name
00238         being optional.
00239         """
00240 
00241     def userFolderDelUsers(names):
00242         """API method for deleting one or more user atom objects. Note that not
00243         all user folder implementations support deletion of user objects."""
00244 
00245     def userFolderAddGroup(name, roles, groups, **kw):
00246         """API method for creating a new group.
00247         """
00248         
00249     def userFolderEditGroup(name, roles, groups, **kw):
00250         """API method for changing group object attributes.
00251         """
00252 
00253     def userFolderUpdateGroup(name, roles, groups, **kw):
00254         """Same as userFolderEditGroup but with all arguments (except name) being
00255         optinal.
00256         """
00257 
00258     def userFolderDelGroups(names):
00259         """API method for deleting one or more group objects.
00260         Implem. note : All ids must be prefixed with 'group_',
00261         so this method ends up beeing only a filter of non-prefixed ids
00262         before calling userFolderDelUsers().
00263         """
00264 
00265     # User mutation
00266 
00267     
00268     # XXX do we have to allow a user to be renamed ?
00269 ##    def setUserId(id, newId):
00270 ##        """Change id of a user atom. The user name might be changed as well by this operation.
00271 ##        """
00272 
00273 ##    def setUserName(id, newName):
00274 ##        """Change the name of a user atom. The user id might be changed as well by this operation.
00275 ##        """
00276 
00277     def userSetRoles(id, roles):
00278         """Change the roles of a user atom
00279         """
00280 
00281     def userAddRole(id, role):
00282         """Append a role for a user atom
00283         """
00284 
00285     def userRemoveRole(id, role):
00286         """Remove the role of a user atom.
00287         This will not, of course, affect implicitly-acquired roles from the user groups.
00288         """
00289 
00290     def userSetPassword(id, newPassword):
00291         """Set the password of a user
00292         """
00293 
00294     def userSetDomains(id, domains):
00295         """Set domains for a user
00296         """
00297 
00298     def userGetDomains(id, ):
00299         """Get domains for a user
00300         """
00301 
00302     def userAddDomain(id, domain):
00303         """Append a domain to a user
00304         """
00305 
00306     def userRemoveDomain(id, domain):
00307         """Remove a domain from a user
00308         """
00309 
00310     def userSetGroups(userid, groupnames):
00311         """Set the groups of a user. Groupnames are, as usual, not prefixed.
00312         However, a groupid can be given as a fallback
00313         """
00314 
00315     def userAddGroup(id, groupname):
00316         """add a group to a user atom. Groupnames are, as usual, not prefixed.
00317         However, a groupid can be given as a fallback
00318         """
00319 
00320     def userRemoveGroup(id, groupname):
00321         """remove a group from a user atom. Groupnames are, as usual, not prefixed.
00322         However, a groupid can be given as a fallback
00323         """
00324 
00325 
00326     # Security management
00327 
00328     def setRolesOnUsers(roles, userids):
00329         """Set a common set of roles for a bunch of user atoms.
00330         """
00331 
00332 ##    def setUsersOfRole(usernames, role):
00333 ##        """Sets the users of a role.
00334 ##        XXX THIS METHOD SEEMS TO BE SEAMLESS.
00335 ##        """
00336 
00337     def getUsersOfRole(role, object = None):
00338         """Gets the user (and group) ids having the specified role...
00339         ...on the specified Zope object if it's not None
00340         ...on their own information if the object is None.
00341         NOTA: THIS METHOD IS VERY EXPENSIVE.
00342         """
00343 
00344     def getRolesOfUser(userid):
00345         """Alias for user.getRoles()
00346         """
00347 
00348     def userFolderAddRole(role):
00349         """Add a new role. The role will be appended, in fact, in GRUF's surrounding folder.
00350         """
00351 
00352     def userFolderDelRoles(roles):
00353         """Delete roles.
00354         The removed roles will be removed from the UserFolder's users and groups as well,
00355         so this method can be very time consuming with a large number of users.
00356         """
00357 
00358     def userFolderGetRoles():
00359         """List the roles defined at the top of GRUF's folder.
00360         """
00361 
00362 
00363     # Groups support
00364     def setMembers(groupid, userids):
00365         """Set the members of the group
00366         """
00367 
00368     def addMember(groupid, id):
00369         """Add a member to a group
00370         """
00371 
00372     def removeMember(groupid, id):
00373         """Remove a member from a group
00374         """
00375 
00376     def hasMember(groupid, id):
00377         """Return true if the specified atom id is in the group.
00378         This is the contrary of IUserAtom.isInGroup(groupid).
00379         THIS CAN BE VERY EXPENSIVE"""
00380 
00381     def getMemberIds(groupid):
00382         """Return the list of member ids (groups and users) in this group.
00383         It will unmangle nested groups as well.
00384         THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
00385         """
00386 
00387     def getUserMemberIds(groupid):
00388         """Same as listMemberIds but only return user ids
00389         THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
00390         """
00391 
00392     def getGroupMemberIds(groupid):
00393         """Same as listMemberUserIds but only return group ids.
00394         THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
00395         """
00396 
00397 
00398     # Local roles acquisition blocking support
00399     def acquireLocalRoles(folder, status):
00400         """Enable or disable local role acquisition on the specified folder.
00401         If status is true, it will enable, else it will disable.
00402         """
00403 
00404     def isLocalRoleAcquired(folder):
00405         """Return true if the specified folder allows local role acquisition.
00406         """
00407 
00408     # Audit & security checking methods
00409 
00410     def getAllLocalRoles(object):
00411         """getAllLocalRoles(self, object): return a dictionnary {user: roles} of local
00412         roles defined AND herited at a certain point. This will handle lr-blocking
00413         as well.
00414         """
00415         
00416 
00417 class IUserAtom(Interface):
00418     """
00419     This interface is an abstract representation of what both a User and a Group can do.
00420     """
00421     # Accessors
00422     
00423     def getId(unprefixed = 0):
00424         """Get the ID of the user. The ID can be used, at least from
00425         Python, to get the user from the user's UserDatabase.
00426         If unprefixed, remove all prefixes in any case."""
00427 
00428     def getUserName():
00429         """Alias for getName()
00430         """
00431 
00432     def getName():
00433         """Get user's or group's name.
00434         For a user, the name can be set by the underlying user folder but usually id == name.
00435         For a group, the ID is prefixed, but the NAME is NOT prefixed by 'group_'.
00436         """
00437 
00438     def getRoles():
00439         """Return the list of roles assigned to a user atom.
00440         This will never return gruf-related roles.
00441         """
00442 
00443     # Properties are defined depending on the underlying user folder: some support
00444     # properties mutation (such as LDAPUserFolder), some do not (such as regular UF).
00445 
00446     def getProperty(name):
00447         """Get a property's value.
00448         Will raise if not available.
00449         """
00450 
00451     def hasProperty(name):
00452         """Return true if the underlying user object has a value for the property.
00453         """
00454 
00455     # Mutators
00456 
00457     def setProperty(name, value):
00458         """Set a property's value.
00459         As some user folders cannot set properties, this method is not guaranteed to work
00460         and will raise a NotImplementedError if the underlying user folder cannot store
00461         properties (or _this_ particular property) for a user.
00462         """
00463         
00464     # XXX We do not allow user name / id changes
00465 ##    def setId(newId):
00466 ##        """Set the id of the user or group. This might change its name as well.
00467 ##        """
00468 
00469 ##    def setName(newName):
00470 ##        """Set the name of the user or group. Depending on the UserFolder implementation,
00471 ##        this might change the id as well.
00472 ##        """
00473 
00474     def setRoles(roles):
00475         """Change user's roles
00476         """
00477 
00478     def addRole(role):
00479         """Append a role to the user
00480         """
00481 
00482     def removeRole(role):
00483         """Remove a role from the user's ones
00484         """
00485 
00486     # Security-related methods
00487 
00488     def getRolesInContext(object):
00489         """Return the list of roles assigned to the user,
00490            including local roles assigned in context of
00491            the passed in object."""
00492 
00493     def has_permission(permission, object):
00494         """Check to see if a user has a given permission on an object."""
00495 
00496     def allowed(object, object_roles=None):
00497         """Check whether the user has access to object. The user must
00498            have one of the roles in object_roles to allow access."""
00499 
00500     def has_role(roles, object=None):
00501         """Check to see if a user has a given role or roles."""
00502 
00503 
00504 
00505     # Group management
00506 
00507     # XXX TODO: CLARIFY ID VS. NAME
00508 
00509     def isGroup():
00510         """Return true if this atom is a group.
00511         """
00512 
00513     def getGroupNames():
00514         """Return the names of the groups that the user or group is directly a member of.
00515         Return an empty list if the user or group doesn't belong to any group.
00516         Doesn't include transitive groups."""
00517 
00518     def getGroupIds():
00519         """Return the names of the groups that the user or group is a member of.
00520         Return an empty list if the user or group doesn't belong to any group.
00521         Doesn't include transitive groups."""
00522 
00523     def getGroups():
00524         """getAllGroupIds() alias.
00525         Return the IDS (not names) of the groups that the user or group is a member of.
00526         Return an empty list if the user or group doesn't belong to any group.
00527         THIS WILL INCLUDE TRANSITIVE GROUPS AS WELL."""
00528 
00529     def getAllGroupIds():
00530         """Return the names of the groups that the user or group is a member of.
00531         Return an empty list if the user or group doesn't belong to any group.
00532         Include transitive groups."""
00533 
00534     def getAllGroupNames():
00535         """Return the names of the groups that the user or group is directly a member of.
00536         Return an empty list if the user or group doesn't belong to any group.
00537         Include transitive groups."""
00538 
00539     def isInGroup(groupid):
00540         """Return true if the user is member of the specified group id
00541         (including transitive groups)"""
00542 
00543     def setGroups(groupids):
00544         """Set 'groupids' groups for the user or group.
00545         """
00546 
00547     def addGroup(groupid):
00548         """Append a group to the current object's groups.
00549         """
00550 
00551     def removeGroup(groupid):
00552         """Remove a group from the object's groups
00553         """
00554 
00555     def getRealId():
00556         """Return group id WITHOUT group prefix.
00557         For a user, return regular user id.
00558         This method is essentially internal.
00559         """
00560 
00561 
00562 class IUser(IUserAtom):
00563     """
00564     A user is a user atom who can log itself on, and
00565     have additional properties such as domains and password.
00566     """
00567     
00568     # Accessors
00569 
00570     def getDomains():
00571         """Return the list of domain restrictions for a user"""
00572 
00573     # Mutators
00574     
00575     def setPassword(newPassword):
00576         """Set user's password
00577         """
00578 
00579     def setDomains(domains):
00580         """Replace domains for the user
00581         """
00582 
00583     def addDomain(domain):
00584         """Append a domain for the user
00585         """
00586 
00587     def removeDomain(domain):
00588         """Remove a domain for the user
00589         """
00590 
00591 
00592 class IGroup(Interface):
00593     """
00594     A group is a user atom other atoms can belong to.
00595     """
00596     def getMemberIds(transitive = 1, ):
00597         """Return the member ids (users and groups) of the atoms of this group.
00598         This method can be very expensive !"""
00599 
00600     def getUserMemberIds(transitive = 1, ):
00601         """Return the member ids (users only) of the users of this group"""
00602 
00603     def getGroupMemberIds(transitive = 1, ):
00604         """Return the members ids (groups only) of the groups of this group"""
00605 
00606     def hasMember(id):
00607         """Return true if the specified atom id is in the group.
00608         This is the contrary of IUserAtom.isInGroup(groupid)"""
00609 
00610     def addMember(userid):
00611          """Add a user the the current group"""
00612          
00613     def removeMember(userid):
00614          """Remove a user from the current group"""