1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
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. #
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. #
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 #######################################################################################
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
32 from OFS
.SimpleItem
import SimpleItem
33 from OFS
.Cache
import Cacheable
36 CACHE_ROOT_GROUPS
= 'getRootGroups'
37 CACHE_GROUPS_OF_GROUP
= 'getGroupsOfGroup'
38 CACHE_USER_NAMES_OF_GROUP
= 'getUserNamesOfGroup'
41 class GroupsTool(BaseTool
, Cacheable
) :
42 """ Groups tool that behave like Membership tool """
44 meta_type
= 'Plinn Groups Tool'
46 security
= ClassSecurityInfo()
48 manage_options
= BaseTool
.manage_options
+ Cacheable
.manage_options
50 security
.declareProtected(AddGroups
, 'getGroupWorkspacesCreationFlag')
53 def _getUserNamesOfGroup(self
, prefixed_group
, no_recurse
= 1) :
54 aclu
= self
.aq_inner
.acl_users
55 allUsers
= aclu
.getPureUsers()
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, ]
64 usersDict
[group
].append(user
.id)
69 security
.declareProtected(ViewGroups
, 'getUserNamesOfGroup')
70 def getUserNamesOfGroup(self
, prefixed_group
, no_recurse
= 1) :
71 """ Return users of groups"""
73 if self
.ZCacheable_isCachingEnabled() :
74 usersDict
= self
.ZCacheable_get(view_name
=CACHE_USER_NAMES_OF_GROUP
,
75 keywords
={'no_recurse' : no_recurse
},
77 if usersDict
is None :
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
})
84 usersDict
= self
._getUserNamesOfGroup
(prefixed_group
, no_recurse
= no_recurse
)
86 return usersDict
.get(prefixed_group
, [])
89 def _getGroupsOfGroup(self
, prefixed_group
) :
90 aclu
= self
.aq_inner
.acl_users
92 allGroups
= aclu
.getGroups()
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, ]
101 groupsDict
[superGroup
].append(group
.id)
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)
113 if groupsDict
is None :
115 groupsDict
= self
._getGroupsOfGroup
(prefixed_group
)
116 self
.ZCacheable_set(groupsDict
, view_name
=CACHE_GROUPS_OF_GROUP
)
118 groupsDict
= self
._getGroupsOfGroup
(prefixed_group
)
120 return groupsDict
.get(prefixed_group
, [])
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
)
128 wGroups
.sort(_sortGroup
)
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()
142 if groups
[0].startswith(prefix
) :
147 prefixLength
= len(prefix
)
148 groups
= [ group
[prefixLength
:] for group
in groups
]
150 for groupId
in allGroupIds
:
151 if groupId
not in groups
:
152 wGroups
.append(self
.getGroupById(groupId
))
155 for groupId
in allGroupIds
:
156 wGroups
.append(self
.getGroupById(groupId
))
159 wGroups
.sort(_sortGroup
)
163 def _getRootGroups(self
) :
165 aclu
= self
.acl_users
166 allGroups
= aclu
.getGroups()
167 groupPrefix
= aclu
.getGroupPrefix()
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
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)
180 if rootGroups
is None :
181 rootGroups
= self
._getRootGroups
()
182 self
.ZCacheable_set(rootGroups
, view_name
=CACHE_ROOT_GROUPS
)
184 rootGroups
= self
._getRootGroups
()
189 security
.declareProtected(ViewGroups
, 'getGroupsWithLocalRole')
190 def getGroupsWithLocalRole(self
, object, role
) :
191 """ Return Groups with local role """
193 aclu
= self
.aq_inner
.acl_users
194 prefix
= aclu
.getGroupPrefix()
195 allGroupNames
= aclu
.getGroupNames()
196 usersAndGroupsWithLocalRole
= object.users_with_local_role(role
)
198 return [ gn
for gn
in usersAndGroupsWithLocalRole
if gn
.startswith(prefix
) ]
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.
206 self
.acl_users
.changeOrCreateGroups(new_groups
= [groupName
, ])
208 group
= self
.getGroupById(groupName
)
209 group
.setGroupProperties(mapping
)
211 if mapping
.get('createArea', None) :
212 self
.createGrouparea(self
.acl_users
.getGroupPrefix()+groupName
)
214 if self
.ZCacheable_isCachingEnabled() :
215 self
.ZCacheable_set(None, view_name
=CACHE_ROOT_GROUPS
)
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
223 ttool
= getToolByName(self
, 'portal_types')
224 ti
= ttool
.getTypeInfo(self
.getGroupWorkspaceContainerType())
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
)
242 # construct without security check
243 group
= self
.getGroupById(id)
244 area
= ti
._constructInstance
(workspaces
, id, title
=group
.getProperty('title', ''))
246 area
.manage_delLocalRoles(area
.users_with_local_role('Owner'))
247 self
.setGroupOwnership(group
, area
)
249 ti
._finishConstruction
(area
)
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
)
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
)
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
)
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
,
277 InitializeClass(GroupsTool
)
280 def _sortGroup(a
, b
) :
281 return cmp(a
.id.lower(), b
.id.lower())