1 # -*- coding: utf-8 -*-
3 ## Copyright (C)2006 Ingeniweb
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 2 of the License, or
8 ## (at your option) any later version.
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; see the file COPYING. If not, write to the
17 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 - [Pure] User: A user is a user atom who can log itself on, and
22 have additional properties such as domains and password.
24 - Group: A group is a user atom other atoms can belong to.
26 - User atom: Abstract representation of either a User or
29 - Member (of a group): User atom inside a group.
31 - Name (of an atom): For a user, the name can be set by
32 the underlying user folder but usually id == name.
33 For a group, its id is prefixed, but its name is NOT prefixed by 'group_'.
34 For method taking a name instead of an id (eg. getUserByName()),
35 if a user and a group have the same name,
36 the USER will have precedence over the group.
38 __version__
= "$Revision: $"
40 # $Id: IUserFolder.py 30098 2006-09-08 12:35:01Z encolpe $
41 __docformat__
= 'restructuredtext'
43 from zope
.interface
import Interface
, Attribute
46 class IUserFolder(Interface
):
49 # Regular Zope UserFolder API #
56 Return a list of all possible user atom names in the system.
57 Groups will be returned WITHOUT their prefix by this method.
58 So, there might be a collision between a user name and a group name.
59 [NOTA: This method is time-expensive !]
64 Return a list of all possible user atom ids in the system.
65 WARNING: Please see the id Vs. name consideration at the
66 top of this document. So, groups will be returned
67 WITH their prefix by this method
68 [NOTA: This method is time-expensive !]
72 """Return the named user atom object or None
73 NOTA: If no user can be found, we try to append a group prefix
74 and fetch the user again before returning 'None'. This will ensure
75 backward compatibility. So in fact, both group id and group name can be
76 specified to this method.
80 """Return a list of user atom objects in the users cache.
81 In case of some UF implementations, the returned object may only be a subset
82 of all possible users.
83 In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()).
84 With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will
85 return only cached user objects instead of fetching all possible users.
86 So this method won't be very time-expensive, but won't be accurate !
89 def getUserById(id, default
):
90 """Return the user atom corresponding to the given id.
91 If default is provided, return default if no user found, else return None.
94 def getUserByName(name
, default
):
95 """Same as getUserById() but works with a name instead of an id.
96 If default is provided, return default if no user found, else return None.
97 [NOTA: Theorically, the id is a handle, while the name is the actual login name.
98 But difference between a user id and a user name is unsignificant in
99 all current User Folder implementations... except for GROUPS.]
104 From Zope 2.7's User.py:
105 This is not a formal API method: it is used only to provide
106 a way for the quickstart page to determine if the default user
107 folder contains any users to provide instructions on how to
108 add a user for newbies. Using getUserNames or getUsers would have
109 posed a denial of service risk.
110 In GRUF, this method always return 1."""
113 # Search interface for users; they won't return groups in any case.
115 def searchUsersByName(search_term
):
116 """Return user ids which match the specified search_term.
117 If search_term is an empty string, behaviour depends on the underlying user folder:
118 it may return all users, return only cached users (for LDAPUF) or return no users.
121 def searchUsersById(search_term
):
122 """Return users whose id match the specified search_term.
123 If search_term is an empty string, behaviour depends on the underlying user folder:
124 it may return all users, return only cached users (for LDAPUF) or return no users.
127 def searchUsersByAttribute(attribute
, search_term
):
128 """Return user ids whose 'attribute' match the specified search_term.
129 If search_term is an empty string, behaviour depends on the underlying user folder:
130 it may return all users, return only cached users (for LDAPUF) or return no users.
131 This will return all users whose name contains search_term (whaterver its case).
132 THIS METHOD MAY BE VERY EXPENSIVE ON USER FOLDER KINDS WHICH DO NOT PROVIDE A
133 SEARCHING METHOD (ie. every UF kind except LDAPUF).
134 'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF.
135 [NOTA: This method is time-expensive !]
138 # Search interface for groups;
140 def searchGroupsByName(search_term
):
141 """Return group ids which match the specified search_term.
142 If search_term is an empty string, behaviour depends on the underlying group folder:
143 it may return all groups, return only cached groups (for LDAPUF) or return no groups.
146 def searchGroupsById(search_term
):
147 """Return groups whose id match the specified search_term.
148 If search_term is an empty string, behaviour depends on the underlying group folder:
149 it may return all groups, return only cached groups (for LDAPUF) or return no groups.
152 def searchGroupsByAttribute(attribute
, search_term
):
153 """Return group ids whose 'attribute' match the specified search_term.
154 If search_term is an empty string, behaviour depends on the underlying group folder:
155 it may return all groups, return only cached groups (for LDAPUF) or return no groups.
156 This will return all groups whose name contains search_term (whaterver its case).
157 THIS METHOD MAY BE VERY EXPENSIVE ON GROUP FOLDER KINDS WHICH DO NOT PROVIDE A
158 SEARCHING METHOD (ie. every UF kind except LDAPUF).
159 'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF.
160 [NOTA: This method is time-expensive !]
166 def getPureUserNames():
167 """Same as getUserNames() but without groups
170 def getPureUserIds():
171 """Same as getUserIds() but without groups
175 """Same as getUsers() but without groups.
179 """Same as getUser() but forces returning a user and not a group
185 """Same as getUserNames() but without pure users.
189 """Same as getUserIds() but without pure users.
193 """Same as getUsers() but without pure users.
194 In case of some UF implementations, the returned object may only be a subset
195 of all possible users.
196 In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()).
197 With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will
198 return only cached user objects instead of fetching all possible users.
199 So this method won't be very time-expensive, but won't be accurate !
203 """Return the named group object or None. As usual, 'id' is prefixed.
206 def getGroupById(id):
207 """Same as getUserById(id) but forces returning a group.
210 def getGroupByName(name
):
211 """Same as getUserByName(name) but forces returning a group.
212 The specified name MUST NOT be prefixed !
218 def userFolderAddUser(name
, password
, roles
, domains
, groups
, **kw
):
219 """API method for creating a new user object. Note that not all
220 user folder implementations support dynamic creation of user
222 Groups can be specified by name or by id (preferabily by name)."""
224 def userFolderEditUser(name
, password
, roles
, domains
, groups
, **kw
):
225 """API method for changing user object attributes. Note that not
226 all user folder implementations support changing of user object
228 Groups can be specified by name or by id (preferabily by name)."""
230 def userFolderUpdateUser(name
, password
, roles
, domains
, groups
, **kw
):
231 """Same as userFolderEditUser, but with all arguments except name
235 def userFolderDelUsers(names
):
236 """API method for deleting one or more user atom objects. Note that not
237 all user folder implementations support deletion of user objects."""
239 def userFolderAddGroup(name
, roles
, groups
, **kw
):
240 """API method for creating a new group.
243 def userFolderEditGroup(name
, roles
, groups
, **kw
):
244 """API method for changing group object attributes.
247 def userFolderUpdateGroup(name
, roles
, groups
, **kw
):
248 """Same as userFolderEditGroup but with all arguments (except name) being
252 def userFolderDelGroups(names
):
253 """API method for deleting one or more group objects.
254 Implem. note : All ids must be prefixed with 'group_',
255 so this method ends up beeing only a filter of non-prefixed ids
256 before calling userFolderDelUsers().
262 # XXX do we have to allow a user to be renamed ?
263 ## def setUserId(id, newId):
264 ## """Change id of a user atom. The user name might be changed as well by this operation.
267 ## def setUserName(id, newName):
268 ## """Change the name of a user atom. The user id might be changed as well by this operation.
271 def userSetRoles(id, roles
):
272 """Change the roles of a user atom
275 def userAddRole(id, role
):
276 """Append a role for a user atom
279 def userRemoveRole(id, role
):
280 """Remove the role of a user atom.
281 This will not, of course, affect implicitly-acquired roles from the user groups.
284 def userSetPassword(id, newPassword
):
285 """Set the password of a user
288 def userSetDomains(id, domains
):
289 """Set domains for a user
292 def userGetDomains(id, ):
293 """Get domains for a user
296 def userAddDomain(id, domain
):
297 """Append a domain to a user
300 def userRemoveDomain(id, domain
):
301 """Remove a domain from a user
304 def userSetGroups(userid
, groupnames
):
305 """Set the groups of a user. Groupnames are, as usual, not prefixed.
306 However, a groupid can be given as a fallback
309 def userAddGroup(id, groupname
):
310 """add a group to a user atom. Groupnames are, as usual, not prefixed.
311 However, a groupid can be given as a fallback
314 def userRemoveGroup(id, groupname
):
315 """remove a group from a user atom. Groupnames are, as usual, not prefixed.
316 However, a groupid can be given as a fallback
320 # Security management
322 def setRolesOnUsers(roles
, userids
):
323 """Set a common set of roles for a bunch of user atoms.
326 ## def setUsersOfRole(usernames, role):
327 ## """Sets the users of a role.
328 ## XXX THIS METHOD SEEMS TO BE SEAMLESS.
331 def getUsersOfRole(role
, object = None):
332 """Gets the user (and group) ids having the specified role...
333 ...on the specified Zope object if it's not None
334 ...on their own information if the object is None.
335 NOTA: THIS METHOD IS VERY EXPENSIVE.
338 def getRolesOfUser(userid
):
339 """Alias for user.getRoles()
342 def userFolderAddRole(role
):
343 """Add a new role. The role will be appended, in fact, in GRUF's surrounding folder.
346 def userFolderDelRoles(roles
):
348 The removed roles will be removed from the UserFolder's users and groups as well,
349 so this method can be very time consuming with a large number of users.
352 def userFolderGetRoles():
353 """List the roles defined at the top of GRUF's folder.
358 def setMembers(groupid
, userids
):
359 """Set the members of the group
362 def addMember(groupid
, id):
363 """Add a member to a group
366 def removeMember(groupid
, id):
367 """Remove a member from a group
370 def hasMember(groupid
, id):
371 """Return true if the specified atom id is in the group.
372 This is the contrary of IUserAtom.isInGroup(groupid).
373 THIS CAN BE VERY EXPENSIVE"""
375 def getMemberIds(groupid
):
376 """Return the list of member ids (groups and users) in this group.
377 It will unmangle nested groups as well.
378 THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
381 def getUserMemberIds(groupid
):
382 """Same as listMemberIds but only return user ids
383 THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
386 def getGroupMemberIds(groupid
):
387 """Same as listMemberUserIds but only return group ids.
388 THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS.
392 # Local roles acquisition blocking support
393 def acquireLocalRoles(folder
, status
):
394 """Enable or disable local role acquisition on the specified folder.
395 If status is true, it will enable, else it will disable.
398 def isLocalRoleAcquired(folder
):
399 """Return true if the specified folder allows local role acquisition.
402 # Audit & security checking methods
404 def getAllLocalRoles(object):
405 """getAllLocalRoles(self, object): return a dictionnary {user: roles} of local
406 roles defined AND herited at a certain point. This will handle lr-blocking
411 class IUserAtom(Interface
):
413 This interface is an abstract representation of what both a User and a Group can do.
417 def getId(unprefixed
= 0):
418 """Get the ID of the user. The ID can be used, at least from
419 Python, to get the user from the user's UserDatabase.
420 If unprefixed, remove all prefixes in any case."""
423 """Alias for getName()
427 """Get user's or group's name.
428 For a user, the name can be set by the underlying user folder but usually id == name.
429 For a group, the ID is prefixed, but the NAME is NOT prefixed by 'group_'.
433 """Return the list of roles assigned to a user atom.
434 This will never return gruf-related roles.
437 # Properties are defined depending on the underlying user folder: some support
438 # properties mutation (such as LDAPUserFolder), some do not (such as regular UF).
440 def getProperty(name
):
441 """Get a property's value.
442 Will raise if not available.
445 def hasProperty(name
):
446 """Return true if the underlying user object has a value for the property.
451 def setProperty(name
, value
):
452 """Set a property's value.
453 As some user folders cannot set properties, this method is not guaranteed to work
454 and will raise a NotImplementedError if the underlying user folder cannot store
455 properties (or _this_ particular property) for a user.
458 # XXX We do not allow user name / id changes
460 ## """Set the id of the user or group. This might change its name as well.
463 ## def setName(newName):
464 ## """Set the name of the user or group. Depending on the UserFolder implementation,
465 ## this might change the id as well.
469 """Change user's roles
473 """Append a role to the user
476 def removeRole(role
):
477 """Remove a role from the user's ones
480 # Security-related methods
482 def getRolesInContext(object):
483 """Return the list of roles assigned to the user,
484 including local roles assigned in context of
485 the passed in object."""
487 def has_permission(permission
, object):
488 """Check to see if a user has a given permission on an object."""
490 def allowed(object, object_roles
=None):
491 """Check whether the user has access to object. The user must
492 have one of the roles in object_roles to allow access."""
494 def has_role(roles
, object=None):
495 """Check to see if a user has a given role or roles."""
501 # XXX TODO: CLARIFY ID VS. NAME
504 """Return true if this atom is a group.
508 """Return the names of the groups that the user or group is directly a member of.
509 Return an empty list if the user or group doesn't belong to any group.
510 Doesn't include transitive groups."""
513 """Return the names of the groups that the user or group is a member of.
514 Return an empty list if the user or group doesn't belong to any group.
515 Doesn't include transitive groups."""
518 """getAllGroupIds() alias.
519 Return the IDS (not names) of the groups that the user or group is a member of.
520 Return an empty list if the user or group doesn't belong to any group.
521 THIS WILL INCLUDE TRANSITIVE GROUPS AS WELL."""
523 def getAllGroupIds():
524 """Return the names of the groups that the user or group is a member of.
525 Return an empty list if the user or group doesn't belong to any group.
526 Include transitive groups."""
528 def getAllGroupNames():
529 """Return the names of the groups that the user or group is directly a member of.
530 Return an empty list if the user or group doesn't belong to any group.
531 Include transitive groups."""
533 def isInGroup(groupid
):
534 """Return true if the user is member of the specified group id
535 (including transitive groups)"""
537 def setGroups(groupids
):
538 """Set 'groupids' groups for the user or group.
541 def addGroup(groupid
):
542 """Append a group to the current object's groups.
545 def removeGroup(groupid
):
546 """Remove a group from the object's groups
550 """Return group id WITHOUT group prefix.
551 For a user, return regular user id.
552 This method is essentially internal.
556 class IUser(IUserAtom
):
558 A user is a user atom who can log itself on, and
559 have additional properties such as domains and password.
565 """Return the list of domain restrictions for a user"""
569 def setPassword(newPassword
):
570 """Set user's password
573 def setDomains(domains
):
574 """Replace domains for the user
577 def addDomain(domain
):
578 """Append a domain for the user
581 def removeDomain(domain
):
582 """Remove a domain for the user
586 class IGroup(Interface
):
588 A group is a user atom other atoms can belong to.
590 def getMemberIds(transitive
= 1, ):
591 """Return the member ids (users and groups) of the atoms of this group.
592 This method can be very expensive !"""
594 def getUserMemberIds(transitive
= 1, ):
595 """Return the member ids (users only) of the users of this group"""
597 def getGroupMemberIds(transitive
= 1, ):
598 """Return the members ids (groups only) of the groups of this group"""
601 """Return true if the specified atom id is in the group.
602 This is the contrary of IUserAtom.isInGroup(groupid)"""
604 def addMember(userid
):
605 """Add a user the the current group"""
607 def removeMember(userid
):
608 """Remove a user from the current group"""