compat zope-2.12
[GroupUserFolder.git] / interfaces / IUserFolder.py
1 # -*- coding: utf-8 -*-
2 ## GroupUserFolder
3 ## Copyright (C)2006 Ingeniweb
4
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.
9
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.
14
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.
18 """
19 VOCABULARY:
20
21 - [Pure] User: A user is a user atom who can log itself on, and
22 have additional properties such as domains and password.
23
24 - Group: A group is a user atom other atoms can belong to.
25
26 - User atom: Abstract representation of either a User or
27 a Group.
28
29 - Member (of a group): User atom inside a group.
30
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.
37 """
38 __version__ = "$Revision: $"
39 # $Source: $
40 # $Id: IUserFolder.py 30098 2006-09-08 12:35:01Z encolpe $
41 __docformat__ = 'restructuredtext'
42
43 from zope.interface import Interface, Attribute
44
45
46 class IUserFolder(Interface):
47
48 # #
49 # Regular Zope UserFolder API #
50 # #
51
52 # User atom access
53
54 def getUserNames():
55 """
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 !]
60 """
61
62 def getUserIds():
63 """
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 !]
69 """
70
71 def getUser(name):
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.
77 """
78
79 def getUsers():
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 !
87 """
88
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.
92 """
93
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.]
100 """
101
102 def hasUsers():
103 """
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."""
111
112
113 # Search interface for users; they won't return groups in any case.
114
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.
119 """
120
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.
125 """
126
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 !]
136 """
137
138 # Search interface for groups;
139
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.
144 """
145
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.
150 """
151
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 !]
161 """
162
163
164 # User access
165
166 def getPureUserNames():
167 """Same as getUserNames() but without groups
168 """
169
170 def getPureUserIds():
171 """Same as getUserIds() but without groups
172 """
173
174 def getPureUsers():
175 """Same as getUsers() but without groups.
176 """
177
178 def getPureUser(id):
179 """Same as getUser() but forces returning a user and not a group
180 """
181
182 # Group access
183
184 def getGroupNames():
185 """Same as getUserNames() but without pure users.
186 """
187
188 def getGroupIds():
189 """Same as getUserIds() but without pure users.
190 """
191
192 def getGroups():
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 !
200 """
201
202 def getGroup(name):
203 """Return the named group object or None. As usual, 'id' is prefixed.
204 """
205
206 def getGroupById(id):
207 """Same as getUserById(id) but forces returning a group.
208 """
209
210 def getGroupByName(name):
211 """Same as getUserByName(name) but forces returning a group.
212 The specified name MUST NOT be prefixed !
213 """
214
215
216 # Mutators
217
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
221 objects.
222 Groups can be specified by name or by id (preferabily by name)."""
223
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
227 attributes.
228 Groups can be specified by name or by id (preferabily by name)."""
229
230 def userFolderUpdateUser(name, password, roles, domains, groups, **kw):
231 """Same as userFolderEditUser, but with all arguments except name
232 being optional.
233 """
234
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."""
238
239 def userFolderAddGroup(name, roles, groups, **kw):
240 """API method for creating a new group.
241 """
242
243 def userFolderEditGroup(name, roles, groups, **kw):
244 """API method for changing group object attributes.
245 """
246
247 def userFolderUpdateGroup(name, roles, groups, **kw):
248 """Same as userFolderEditGroup but with all arguments (except name) being
249 optinal.
250 """
251
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().
257 """
258
259 # User mutation
260
261
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.
265 ## """
266
267 ## def setUserName(id, newName):
268 ## """Change the name of a user atom. The user id might be changed as well by this operation.
269 ## """
270
271 def userSetRoles(id, roles):
272 """Change the roles of a user atom
273 """
274
275 def userAddRole(id, role):
276 """Append a role for a user atom
277 """
278
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.
282 """
283
284 def userSetPassword(id, newPassword):
285 """Set the password of a user
286 """
287
288 def userSetDomains(id, domains):
289 """Set domains for a user
290 """
291
292 def userGetDomains(id, ):
293 """Get domains for a user
294 """
295
296 def userAddDomain(id, domain):
297 """Append a domain to a user
298 """
299
300 def userRemoveDomain(id, domain):
301 """Remove a domain from a user
302 """
303
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
307 """
308
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
312 """
313
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
317 """
318
319
320 # Security management
321
322 def setRolesOnUsers(roles, userids):
323 """Set a common set of roles for a bunch of user atoms.
324 """
325
326 ## def setUsersOfRole(usernames, role):
327 ## """Sets the users of a role.
328 ## XXX THIS METHOD SEEMS TO BE SEAMLESS.
329 ## """
330
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.
336 """
337
338 def getRolesOfUser(userid):
339 """Alias for user.getRoles()
340 """
341
342 def userFolderAddRole(role):
343 """Add a new role. The role will be appended, in fact, in GRUF's surrounding folder.
344 """
345
346 def userFolderDelRoles(roles):
347 """Delete 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.
350 """
351
352 def userFolderGetRoles():
353 """List the roles defined at the top of GRUF's folder.
354 """
355
356
357 # Groups support
358 def setMembers(groupid, userids):
359 """Set the members of the group
360 """
361
362 def addMember(groupid, id):
363 """Add a member to a group
364 """
365
366 def removeMember(groupid, id):
367 """Remove a member from a group
368 """
369
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"""
374
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.
379 """
380
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.
384 """
385
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.
389 """
390
391
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.
396 """
397
398 def isLocalRoleAcquired(folder):
399 """Return true if the specified folder allows local role acquisition.
400 """
401
402 # Audit & security checking methods
403
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
407 as well.
408 """
409
410
411 class IUserAtom(Interface):
412 """
413 This interface is an abstract representation of what both a User and a Group can do.
414 """
415 # Accessors
416
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."""
421
422 def getUserName():
423 """Alias for getName()
424 """
425
426 def 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_'.
430 """
431
432 def getRoles():
433 """Return the list of roles assigned to a user atom.
434 This will never return gruf-related roles.
435 """
436
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).
439
440 def getProperty(name):
441 """Get a property's value.
442 Will raise if not available.
443 """
444
445 def hasProperty(name):
446 """Return true if the underlying user object has a value for the property.
447 """
448
449 # Mutators
450
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.
456 """
457
458 # XXX We do not allow user name / id changes
459 ## def setId(newId):
460 ## """Set the id of the user or group. This might change its name as well.
461 ## """
462
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.
466 ## """
467
468 def setRoles(roles):
469 """Change user's roles
470 """
471
472 def addRole(role):
473 """Append a role to the user
474 """
475
476 def removeRole(role):
477 """Remove a role from the user's ones
478 """
479
480 # Security-related methods
481
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."""
486
487 def has_permission(permission, object):
488 """Check to see if a user has a given permission on an object."""
489
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."""
493
494 def has_role(roles, object=None):
495 """Check to see if a user has a given role or roles."""
496
497
498
499 # Group management
500
501 # XXX TODO: CLARIFY ID VS. NAME
502
503 def isGroup():
504 """Return true if this atom is a group.
505 """
506
507 def getGroupNames():
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."""
511
512 def getGroupIds():
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."""
516
517 def getGroups():
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."""
522
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."""
527
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."""
532
533 def isInGroup(groupid):
534 """Return true if the user is member of the specified group id
535 (including transitive groups)"""
536
537 def setGroups(groupids):
538 """Set 'groupids' groups for the user or group.
539 """
540
541 def addGroup(groupid):
542 """Append a group to the current object's groups.
543 """
544
545 def removeGroup(groupid):
546 """Remove a group from the object's groups
547 """
548
549 def getRealId():
550 """Return group id WITHOUT group prefix.
551 For a user, return regular user id.
552 This method is essentially internal.
553 """
554
555
556 class IUser(IUserAtom):
557 """
558 A user is a user atom who can log itself on, and
559 have additional properties such as domains and password.
560 """
561
562 # Accessors
563
564 def getDomains():
565 """Return the list of domain restrictions for a user"""
566
567 # Mutators
568
569 def setPassword(newPassword):
570 """Set user's password
571 """
572
573 def setDomains(domains):
574 """Replace domains for the user
575 """
576
577 def addDomain(domain):
578 """Append a domain for the user
579 """
580
581 def removeDomain(domain):
582 """Remove a domain for the user
583 """
584
585
586 class IGroup(Interface):
587 """
588 A group is a user atom other atoms can belong to.
589 """
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 !"""
593
594 def getUserMemberIds(transitive = 1, ):
595 """Return the member ids (users only) of the users of this group"""
596
597 def getGroupMemberIds(transitive = 1, ):
598 """Return the members ids (groups only) of the groups of this group"""
599
600 def hasMember(id):
601 """Return true if the specified atom id is in the group.
602 This is the contrary of IUserAtom.isInGroup(groupid)"""
603
604 def addMember(userid):
605 """Add a user the the current group"""
606
607 def removeMember(userid):
608 """Remove a user from the current group"""