X-Git-Url: https://scm.cri.minesparis.psl.eu/git/GroupUserFolder.git/blobdiff_plain/e9d14b6b5cc9cd4775c60cb340b5c4c787536fc3..3e1ba4932c34812cf2f6f3569b0f0dbea97b7a0b:/Products/GroupUserFolder/interfaces/IUserFolder.py diff --git a/Products/GroupUserFolder/interfaces/IUserFolder.py b/Products/GroupUserFolder/interfaces/IUserFolder.py new file mode 100644 index 0000000..026a612 --- /dev/null +++ b/Products/GroupUserFolder/interfaces/IUserFolder.py @@ -0,0 +1,608 @@ +# -*- coding: utf-8 -*- +## GroupUserFolder +## Copyright (C)2006 Ingeniweb + +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; see the file COPYING. If not, write to the +## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +""" +VOCABULARY: + + - [Pure] User: A user is a user atom who can log itself on, and + have additional properties such as domains and password. + + - Group: A group is a user atom other atoms can belong to. + + - User atom: Abstract representation of either a User or + a Group. + + - Member (of a group): User atom inside a group. + + - Name (of an atom): For a user, the name can be set by + the underlying user folder but usually id == name. + For a group, its id is prefixed, but its name is NOT prefixed by 'group_'. + For method taking a name instead of an id (eg. getUserByName()), + if a user and a group have the same name, + the USER will have precedence over the group. +""" +__version__ = "$Revision: $" +# $Source: $ +# $Id: IUserFolder.py 30098 2006-09-08 12:35:01Z encolpe $ +__docformat__ = 'restructuredtext' + +from zope.interface import Interface, Attribute + + +class IUserFolder(Interface): + + # # + # Regular Zope UserFolder API # + # # + + # User atom access + + def getUserNames(): + """ + Return a list of all possible user atom names in the system. + Groups will be returned WITHOUT their prefix by this method. + So, there might be a collision between a user name and a group name. + [NOTA: This method is time-expensive !] + """ + + def getUserIds(): + """ + Return a list of all possible user atom ids in the system. + WARNING: Please see the id Vs. name consideration at the + top of this document. So, groups will be returned + WITH their prefix by this method + [NOTA: This method is time-expensive !] + """ + + def getUser(name): + """Return the named user atom object or None + NOTA: If no user can be found, we try to append a group prefix + and fetch the user again before returning 'None'. This will ensure + backward compatibility. So in fact, both group id and group name can be + specified to this method. + """ + + def getUsers(): + """Return a list of user atom objects in the users cache. + In case of some UF implementations, the returned object may only be a subset + of all possible users. + In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()). + With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will + return only cached user objects instead of fetching all possible users. + So this method won't be very time-expensive, but won't be accurate ! + """ + + def getUserById(id, default): + """Return the user atom corresponding to the given id. + If default is provided, return default if no user found, else return None. + """ + + def getUserByName(name, default): + """Same as getUserById() but works with a name instead of an id. + If default is provided, return default if no user found, else return None. + [NOTA: Theorically, the id is a handle, while the name is the actual login name. + But difference between a user id and a user name is unsignificant in + all current User Folder implementations... except for GROUPS.] + """ + + def hasUsers(): + """ + From Zope 2.7's User.py: + This is not a formal API method: it is used only to provide + a way for the quickstart page to determine if the default user + folder contains any users to provide instructions on how to + add a user for newbies. Using getUserNames or getUsers would have + posed a denial of service risk. + In GRUF, this method always return 1.""" + + + # Search interface for users; they won't return groups in any case. + + def searchUsersByName(search_term): + """Return user ids which match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying user folder: + it may return all users, return only cached users (for LDAPUF) or return no users. + """ + + def searchUsersById(search_term): + """Return users whose id match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying user folder: + it may return all users, return only cached users (for LDAPUF) or return no users. + """ + + def searchUsersByAttribute(attribute, search_term): + """Return user ids whose 'attribute' match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying user folder: + it may return all users, return only cached users (for LDAPUF) or return no users. + This will return all users whose name contains search_term (whaterver its case). + THIS METHOD MAY BE VERY EXPENSIVE ON USER FOLDER KINDS WHICH DO NOT PROVIDE A + SEARCHING METHOD (ie. every UF kind except LDAPUF). + 'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF. + [NOTA: This method is time-expensive !] + """ + + # Search interface for groups; + + def searchGroupsByName(search_term): + """Return group ids which match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying group folder: + it may return all groups, return only cached groups (for LDAPUF) or return no groups. + """ + + def searchGroupsById(search_term): + """Return groups whose id match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying group folder: + it may return all groups, return only cached groups (for LDAPUF) or return no groups. + """ + + def searchGroupsByAttribute(attribute, search_term): + """Return group ids whose 'attribute' match the specified search_term. + If search_term is an empty string, behaviour depends on the underlying group folder: + it may return all groups, return only cached groups (for LDAPUF) or return no groups. + This will return all groups whose name contains search_term (whaterver its case). + THIS METHOD MAY BE VERY EXPENSIVE ON GROUP FOLDER KINDS WHICH DO NOT PROVIDE A + SEARCHING METHOD (ie. every UF kind except LDAPUF). + 'attribute' can be 'id' or 'name' for all UF kinds, or anything else for LDAPUF. + [NOTA: This method is time-expensive !] + """ + + + # User access + + def getPureUserNames(): + """Same as getUserNames() but without groups + """ + + def getPureUserIds(): + """Same as getUserIds() but without groups + """ + + def getPureUsers(): + """Same as getUsers() but without groups. + """ + + def getPureUser(id): + """Same as getUser() but forces returning a user and not a group + """ + + # Group access + + def getGroupNames(): + """Same as getUserNames() but without pure users. + """ + + def getGroupIds(): + """Same as getUserIds() but without pure users. + """ + + def getGroups(): + """Same as getUsers() but without pure users. + In case of some UF implementations, the returned object may only be a subset + of all possible users. + In other words, you CANNOT assert that len(getUsers()) equals len(getUserNames()). + With cache-support UserFolders, such as LDAPUserFolder, the getUser() method will + return only cached user objects instead of fetching all possible users. + So this method won't be very time-expensive, but won't be accurate ! + """ + + def getGroup(name): + """Return the named group object or None. As usual, 'id' is prefixed. + """ + + def getGroupById(id): + """Same as getUserById(id) but forces returning a group. + """ + + def getGroupByName(name): + """Same as getUserByName(name) but forces returning a group. + The specified name MUST NOT be prefixed ! + """ + + + # Mutators + + def userFolderAddUser(name, password, roles, domains, groups, **kw): + """API method for creating a new user object. Note that not all + user folder implementations support dynamic creation of user + objects. + Groups can be specified by name or by id (preferabily by name).""" + + def userFolderEditUser(name, password, roles, domains, groups, **kw): + """API method for changing user object attributes. Note that not + all user folder implementations support changing of user object + attributes. + Groups can be specified by name or by id (preferabily by name).""" + + def userFolderUpdateUser(name, password, roles, domains, groups, **kw): + """Same as userFolderEditUser, but with all arguments except name + being optional. + """ + + def userFolderDelUsers(names): + """API method for deleting one or more user atom objects. Note that not + all user folder implementations support deletion of user objects.""" + + def userFolderAddGroup(name, roles, groups, **kw): + """API method for creating a new group. + """ + + def userFolderEditGroup(name, roles, groups, **kw): + """API method for changing group object attributes. + """ + + def userFolderUpdateGroup(name, roles, groups, **kw): + """Same as userFolderEditGroup but with all arguments (except name) being + optinal. + """ + + def userFolderDelGroups(names): + """API method for deleting one or more group objects. + Implem. note : All ids must be prefixed with 'group_', + so this method ends up beeing only a filter of non-prefixed ids + before calling userFolderDelUsers(). + """ + + # User mutation + + + # XXX do we have to allow a user to be renamed ? +## def setUserId(id, newId): +## """Change id of a user atom. The user name might be changed as well by this operation. +## """ + +## def setUserName(id, newName): +## """Change the name of a user atom. The user id might be changed as well by this operation. +## """ + + def userSetRoles(id, roles): + """Change the roles of a user atom + """ + + def userAddRole(id, role): + """Append a role for a user atom + """ + + def userRemoveRole(id, role): + """Remove the role of a user atom. + This will not, of course, affect implicitly-acquired roles from the user groups. + """ + + def userSetPassword(id, newPassword): + """Set the password of a user + """ + + def userSetDomains(id, domains): + """Set domains for a user + """ + + def userGetDomains(id, ): + """Get domains for a user + """ + + def userAddDomain(id, domain): + """Append a domain to a user + """ + + def userRemoveDomain(id, domain): + """Remove a domain from a user + """ + + def userSetGroups(userid, groupnames): + """Set the groups of a user. Groupnames are, as usual, not prefixed. + However, a groupid can be given as a fallback + """ + + def userAddGroup(id, groupname): + """add a group to a user atom. Groupnames are, as usual, not prefixed. + However, a groupid can be given as a fallback + """ + + def userRemoveGroup(id, groupname): + """remove a group from a user atom. Groupnames are, as usual, not prefixed. + However, a groupid can be given as a fallback + """ + + + # Security management + + def setRolesOnUsers(roles, userids): + """Set a common set of roles for a bunch of user atoms. + """ + +## def setUsersOfRole(usernames, role): +## """Sets the users of a role. +## XXX THIS METHOD SEEMS TO BE SEAMLESS. +## """ + + def getUsersOfRole(role, object = None): + """Gets the user (and group) ids having the specified role... + ...on the specified Zope object if it's not None + ...on their own information if the object is None. + NOTA: THIS METHOD IS VERY EXPENSIVE. + """ + + def getRolesOfUser(userid): + """Alias for user.getRoles() + """ + + def userFolderAddRole(role): + """Add a new role. The role will be appended, in fact, in GRUF's surrounding folder. + """ + + def userFolderDelRoles(roles): + """Delete roles. + The removed roles will be removed from the UserFolder's users and groups as well, + so this method can be very time consuming with a large number of users. + """ + + def userFolderGetRoles(): + """List the roles defined at the top of GRUF's folder. + """ + + + # Groups support + def setMembers(groupid, userids): + """Set the members of the group + """ + + def addMember(groupid, id): + """Add a member to a group + """ + + def removeMember(groupid, id): + """Remove a member from a group + """ + + def hasMember(groupid, id): + """Return true if the specified atom id is in the group. + This is the contrary of IUserAtom.isInGroup(groupid). + THIS CAN BE VERY EXPENSIVE""" + + def getMemberIds(groupid): + """Return the list of member ids (groups and users) in this group. + It will unmangle nested groups as well. + THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS. + """ + + def getUserMemberIds(groupid): + """Same as listMemberIds but only return user ids + THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS. + """ + + def getGroupMemberIds(groupid): + """Same as listMemberUserIds but only return group ids. + THIS METHOD CAN BE VERY EXPENSIVE AS IT NEEDS TO FETCH ALL USERS. + """ + + + # Local roles acquisition blocking support + def acquireLocalRoles(folder, status): + """Enable or disable local role acquisition on the specified folder. + If status is true, it will enable, else it will disable. + """ + + def isLocalRoleAcquired(folder): + """Return true if the specified folder allows local role acquisition. + """ + + # Audit & security checking methods + + def getAllLocalRoles(object): + """getAllLocalRoles(self, object): return a dictionnary {user: roles} of local + roles defined AND herited at a certain point. This will handle lr-blocking + as well. + """ + + +class IUserAtom(Interface): + """ + This interface is an abstract representation of what both a User and a Group can do. + """ + # Accessors + + def getId(unprefixed = 0): + """Get the ID of the user. The ID can be used, at least from + Python, to get the user from the user's UserDatabase. + If unprefixed, remove all prefixes in any case.""" + + def getUserName(): + """Alias for getName() + """ + + def getName(): + """Get user's or group's name. + For a user, the name can be set by the underlying user folder but usually id == name. + For a group, the ID is prefixed, but the NAME is NOT prefixed by 'group_'. + """ + + def getRoles(): + """Return the list of roles assigned to a user atom. + This will never return gruf-related roles. + """ + + # Properties are defined depending on the underlying user folder: some support + # properties mutation (such as LDAPUserFolder), some do not (such as regular UF). + + def getProperty(name): + """Get a property's value. + Will raise if not available. + """ + + def hasProperty(name): + """Return true if the underlying user object has a value for the property. + """ + + # Mutators + + def setProperty(name, value): + """Set a property's value. + As some user folders cannot set properties, this method is not guaranteed to work + and will raise a NotImplementedError if the underlying user folder cannot store + properties (or _this_ particular property) for a user. + """ + + # XXX We do not allow user name / id changes +## def setId(newId): +## """Set the id of the user or group. This might change its name as well. +## """ + +## def setName(newName): +## """Set the name of the user or group. Depending on the UserFolder implementation, +## this might change the id as well. +## """ + + def setRoles(roles): + """Change user's roles + """ + + def addRole(role): + """Append a role to the user + """ + + def removeRole(role): + """Remove a role from the user's ones + """ + + # Security-related methods + + def getRolesInContext(object): + """Return the list of roles assigned to the user, + including local roles assigned in context of + the passed in object.""" + + def has_permission(permission, object): + """Check to see if a user has a given permission on an object.""" + + def allowed(object, object_roles=None): + """Check whether the user has access to object. The user must + have one of the roles in object_roles to allow access.""" + + def has_role(roles, object=None): + """Check to see if a user has a given role or roles.""" + + + + # Group management + + # XXX TODO: CLARIFY ID VS. NAME + + def isGroup(): + """Return true if this atom is a group. + """ + + def getGroupNames(): + """Return the names of the groups that the user or group is directly a member of. + Return an empty list if the user or group doesn't belong to any group. + Doesn't include transitive groups.""" + + def getGroupIds(): + """Return the names of the groups that the user or group is a member of. + Return an empty list if the user or group doesn't belong to any group. + Doesn't include transitive groups.""" + + def getGroups(): + """getAllGroupIds() alias. + Return the IDS (not names) of the groups that the user or group is a member of. + Return an empty list if the user or group doesn't belong to any group. + THIS WILL INCLUDE TRANSITIVE GROUPS AS WELL.""" + + def getAllGroupIds(): + """Return the names of the groups that the user or group is a member of. + Return an empty list if the user or group doesn't belong to any group. + Include transitive groups.""" + + def getAllGroupNames(): + """Return the names of the groups that the user or group is directly a member of. + Return an empty list if the user or group doesn't belong to any group. + Include transitive groups.""" + + def isInGroup(groupid): + """Return true if the user is member of the specified group id + (including transitive groups)""" + + def setGroups(groupids): + """Set 'groupids' groups for the user or group. + """ + + def addGroup(groupid): + """Append a group to the current object's groups. + """ + + def removeGroup(groupid): + """Remove a group from the object's groups + """ + + def getRealId(): + """Return group id WITHOUT group prefix. + For a user, return regular user id. + This method is essentially internal. + """ + + +class IUser(IUserAtom): + """ + A user is a user atom who can log itself on, and + have additional properties such as domains and password. + """ + + # Accessors + + def getDomains(): + """Return the list of domain restrictions for a user""" + + # Mutators + + def setPassword(newPassword): + """Set user's password + """ + + def setDomains(domains): + """Replace domains for the user + """ + + def addDomain(domain): + """Append a domain for the user + """ + + def removeDomain(domain): + """Remove a domain for the user + """ + + +class IGroup(Interface): + """ + A group is a user atom other atoms can belong to. + """ + def getMemberIds(transitive = 1, ): + """Return the member ids (users and groups) of the atoms of this group. + This method can be very expensive !""" + + def getUserMemberIds(transitive = 1, ): + """Return the member ids (users only) of the users of this group""" + + def getGroupMemberIds(transitive = 1, ): + """Return the members ids (groups only) of the groups of this group""" + + def hasMember(id): + """Return true if the specified atom id is in the group. + This is the contrary of IUserAtom.isInGroup(groupid)""" + + def addMember(userid): + """Add a user the the current group""" + + def removeMember(userid): + """Remove a user from the current group"""