bugfix : on vérifie que le parent implémente bien l'interface d'ordonancement.
[Plinn.git] / GroupsTool.py
1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
5 # #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program; if not, write to the Free Software #
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
19 #######################################################################################
20 """
21
22
23 """
24
25 from Globals import InitializeClass
26 from AccessControl import ClassSecurityInfo
27 from Products.CMFCore.permissions import View, AccessContentsInformation
28 from Products.CMFCore.utils import getToolByName
29 from Products.GroupUserFolder.GroupsToolPermissions import ViewGroups, AddGroups, DeleteGroups
30 from Products.GroupUserFolder.GroupsTool import GroupsTool as BaseTool
31 from sets import Set
32 from OFS.SimpleItem import SimpleItem
33 from OFS.Cache import Cacheable
34
35 #Cache view names
36 CACHE_ROOT_GROUPS = 'getRootGroups'
37 CACHE_GROUPS_OF_GROUP = 'getGroupsOfGroup'
38 CACHE_USER_NAMES_OF_GROUP= 'getUserNamesOfGroup'
39
40
41 class GroupsTool(BaseTool, Cacheable) :
42 """ Groups tool that behave like Membership tool """
43
44 meta_type = 'Plinn Groups Tool'
45
46 security = ClassSecurityInfo()
47
48 manage_options = BaseTool.manage_options + Cacheable.manage_options
49
50 security.declareProtected(AddGroups, 'getGroupWorkspacesCreationFlag')
51
52
53 def _getUserNamesOfGroup(self, prefixed_group, no_recurse = 1) :
54 aclu = self.aq_inner.acl_users
55 allUsers = aclu.getPureUsers()
56 usersDict = {}
57
58 # make a dictionary of users indexed by group
59 for user in allUsers :
60 for group in user.getGroups(no_recurse = no_recurse) :
61 if not usersDict.has_key(group) :
62 usersDict[group] = [user.id, ]
63 else :
64 usersDict[group].append(user.id)
65 return usersDict
66
67
68
69 security.declareProtected(ViewGroups, 'getUserNamesOfGroup')
70 def getUserNamesOfGroup(self, prefixed_group, no_recurse = 1) :
71 """ Return users of groups"""
72
73 if self.ZCacheable_isCachingEnabled() :
74 usersDict = self.ZCacheable_get(view_name=CACHE_USER_NAMES_OF_GROUP,
75 keywords={'no_recurse' : no_recurse},
76 default=None)
77 if usersDict is None :
78 # load cache
79 usersDict = self._getUserNamesOfGroup(prefixed_group, no_recurse = no_recurse)
80 self.ZCacheable_set(usersDict,
81 view_name=CACHE_USER_NAMES_OF_GROUP,
82 keywords={'no_recurse' : no_recurse})
83 else :
84 usersDict = self._getUserNamesOfGroup(prefixed_group, no_recurse = no_recurse)
85
86 return usersDict.get(prefixed_group, [])
87
88
89 def _getGroupsOfGroup(self, prefixed_group) :
90 aclu = self.aq_inner.acl_users
91
92 allGroups = aclu.getGroups()
93 groupsDict = {}
94
95 # make a dictionary of users indexed by group
96 for group in allGroups :
97 for superGroup in group.getGroups(no_recurse=1) :
98 if not groupsDict.has_key(superGroup) :
99 groupsDict[superGroup] = [group.id, ]
100 else :
101 groupsDict[superGroup].append(group.id)
102
103 return groupsDict
104
105
106
107 security.declareProtected(ViewGroups, 'getGroupsOfGroup')
108 def getGroupsOfGroup(self, prefixed_group) :
109 """ Return groups of group """
110 if self.ZCacheable_isCachingEnabled() :
111 groupsDict = self.ZCacheable_get(view_name=CACHE_GROUPS_OF_GROUP, default=None)
112
113 if groupsDict is None :
114 # load cache
115 groupsDict = self._getGroupsOfGroup(prefixed_group)
116 self.ZCacheable_set(groupsDict, view_name=CACHE_GROUPS_OF_GROUP)
117 else :
118 groupsDict = self._getGroupsOfGroup(prefixed_group)
119
120 return groupsDict.get(prefixed_group, [])
121
122 security.declareProtected(ViewGroups, 'getGroups')
123 def getGroups(self, groups) :
124 """ Return wrapped groups """
125 wGroups = [ self.getGroupById(group) for group in groups ]
126 wGroups = filter(None, wGroups)
127
128 wGroups.sort(_sortGroup)
129 return wGroups
130
131 security.declareProtected(ViewGroups, 'getOtherGroups')
132 def getOtherGroups(self, groups) :
133 """ Return other wrapped groups """
134 aclu = self.aq_inner.acl_users
135 prefix = aclu.getGroupPrefix()
136 allGroupIds = aclu.getGroupNames()
137
138
139 prefixed = 0
140 wGroups = []
141 if groups :
142 if groups[0].startswith(prefix) :
143 prefixed = 1
144
145
146 if prefixed :
147 prefixLength = len(prefix)
148 groups = [ group[prefixLength:] for group in groups ]
149
150 for groupId in allGroupIds :
151 if groupId not in groups :
152 wGroups.append(self.getGroupById(groupId))
153
154 else :
155 for groupId in allGroupIds :
156 wGroups.append(self.getGroupById(groupId))
157
158
159 wGroups.sort(_sortGroup)
160 return wGroups
161
162
163 def _getRootGroups(self) :
164 top_level_list = []
165 aclu = self.acl_users
166 allGroups = aclu.getGroups()
167 groupPrefix = aclu.getGroupPrefix()
168
169 for group in allGroups :
170 if not group.getGroups(no_recurse = 1) :
171 top_level_list.append(groupPrefix+group.id)
172 return top_level_list
173
174 security.declareProtected(ViewGroups, 'getRootGroups')
175 def getRootGroups(self) :
176 """ return top level groups """
177 if self.ZCacheable_isCachingEnabled() :
178 rootGroups = self.ZCacheable_get(view_name=CACHE_ROOT_GROUPS, default=None)
179
180 if rootGroups is None :
181 rootGroups = self._getRootGroups()
182 self.ZCacheable_set(rootGroups, view_name=CACHE_ROOT_GROUPS)
183 else :
184 rootGroups = self._getRootGroups()
185
186 return rootGroups
187
188
189 security.declareProtected(ViewGroups, 'getGroupsWithLocalRole')
190 def getGroupsWithLocalRole(self, object, role) :
191 """ Return Groups with local role """
192
193 aclu = self.aq_inner.acl_users
194 prefix = aclu.getGroupPrefix()
195 allGroupNames = aclu.getGroupNames()
196 usersAndGroupsWithLocalRole = object.users_with_local_role(role)
197
198 return [ gn for gn in usersAndGroupsWithLocalRole if gn.startswith(prefix) ]
199
200
201 security.declareProtected(AddGroups, 'addGroup')
202 def addGroup(self, groupName, **mapping):
203 """ Create a group, and a group workspace if the toggle is on,
204 with the supplied id, roles, and domains.
205 """
206 self.acl_users.changeOrCreateGroups(new_groups = [groupName, ])
207
208 group = self.getGroupById(groupName)
209 group.setGroupProperties(mapping)
210
211 if mapping.get('createArea', None) :
212 self.createGrouparea(self.acl_users.getGroupPrefix()+groupName)
213
214 if self.ZCacheable_isCachingEnabled() :
215 self.ZCacheable_set(None, view_name=CACHE_ROOT_GROUPS)
216
217
218 security.declareProtected(AddGroups, 'createGrouparea')
219 def createGrouparea(self, id):
220 """Create a space in the portal for the given group, much like member home
221 folders."""
222
223 ttool = getToolByName(self, 'portal_types')
224 ti = ttool.getTypeInfo(self.getGroupWorkspaceContainerType())
225
226 utool = getToolByName(self, 'portal_url')
227 portal = utool.getPortalObject()
228 workspaces = self.getGroupWorkspacesFolder()
229 if workspaces is None :
230 portalOwner = portal.getOwner()
231 aclu = self.aq_inner.acl_users
232 portalOwner = portalOwner.__of__(aclu)
233 workspaces = ti._constructInstance(portal,
234 self.getGroupWorkspacesFolderId(),
235 title=self.getGroupWorkspacesFolderTitle())
236 workspaces.manage_delLocalRoles(workspaces.users_with_local_role('Owner'))
237 workspaces.changeOwnership(portalOwner)
238 ti._finishConstruction(workspaces)
239
240
241
242 # construct without security check
243 group = self.getGroupById(id)
244 area = ti._constructInstance(workspaces, id, title=group.getProperty('title', ''))
245
246 area.manage_delLocalRoles(area.users_with_local_role('Owner'))
247 self.setGroupOwnership(group, area)
248
249 ti._finishConstruction(area)
250
251
252 security.declareProtected(DeleteGroups, 'removeGroups')
253 def removeGroups(self, ids, keep_workspaces=0) :
254 """ remove the groups and invalidate cache """
255 BaseTool.removeGroups(self, ids, keep_workspaces=keep_workspaces)
256 if self.ZCacheable_isCachingEnabled() :
257 self.ZCacheable_set(None, view_name=CACHE_ROOT_GROUPS)
258 self.ZCacheable_set(None, view_name=CACHE_GROUPS_OF_GROUP)
259
260 security.declareProtected(ViewGroups, 'getExplAndImplGroupsByUserId')
261 def getExplAndImplGroupsByUserId(self, userid) :
262 """ Return a dictionary with implicit and explicit wrapped groups """
263 aclu = self.aq_inner.acl_users
264 user = aclu.getUser(userid)
265 if user :
266 expl = Set(self.aq_inner.acl_users.getUser(userid).getGroups(no_recurse = 1) or [])
267 implDbl = Set(self.aq_inner.acl_users.getUser(userid).getGroups(no_recurse = 0) or [])
268 impl = implDbl.difference(expl)
269 # wrap
270 expl = [self.getGroupById(gid) for gid in expl]
271 impl = [self.getGroupById(gid) for gid in impl]
272 expl.sort(_sortGroup)
273 impl.sort(_sortGroup)
274 return {'explicit' : expl,
275 'implicit' : impl}
276
277 InitializeClass(GroupsTool)
278
279
280 def _sortGroup(a, b) :
281 return cmp(a.id.lower(), b.id.lower())