def __init__(self, context, parent=None, groupid=u'', title=u'', description=u'', namespace=u'', roles=(), members=None, **kwargs): if not IWorkspaceContext.providedBy(context): raise ValueError('Could not adapt: context not a workspace') schema = interfaces.IWorkspaceGroup if schema.providedBy(parent): self.__parent__ = parent self.context = context self.adapts_project = IProjectContext.providedBy(context) valid_setattr(self, schema['baseid'], _decode(groupid)) valid_setattr(self, schema['title'], _decode(title)) valid_setattr(self, schema['description'], _decode(description)) valid_setattr(self, schema['namespace'], _decode(namespace)) self._keys = None self.portal = getSite() self.site_members = members or interfaces.ISiteMembers(self.portal) groups = Groups(self.portal) groupname = self.pas_group()[0] if groupname not in groups: groups.add(groupname) # edge-case: may cause write-on-read self._group = GroupInfo(groupname, members=self.site_members)
class WorkspaceGroup(object): """ Workspace group adapter: provides mapping for managing workspace membership in a specific group. """ implements(interfaces.IWorkspaceGroup) adapts(IWorkspaceContext) # class attribute defaults (for instance attributes): __parent__ = None def __init__(self, context, parent=None, groupid=u'', title=u'', description=u'', namespace=u'', roles=(), members=None, **kwargs): if not IWorkspaceContext.providedBy(context): raise ValueError('Could not adapt: context not a workspace') schema = interfaces.IWorkspaceGroup if schema.providedBy(parent): self.__parent__ = parent self.context = context self.adapts_project = IProjectContext.providedBy(context) valid_setattr(self, schema['baseid'], _decode(groupid)) valid_setattr(self, schema['title'], _decode(title)) valid_setattr(self, schema['description'], _decode(description)) valid_setattr(self, schema['namespace'], _decode(namespace)) self._keys = None self.portal = getSite() self.site_members = members or interfaces.ISiteMembers(self.portal) groups = Groups(self.portal) groupname = self.pas_group()[0] if groupname not in groups: groups.add(groupname) # edge-case: may cause write-on-read self._group = GroupInfo(groupname, members=self.site_members) @property def __name__(self): return self.baseid or None def _groupname(self): ns = self.namespace # usually UUID of workspace return '-'.join((ns, self.baseid)) def _grouptitle(self): r = [] # stack of object context (LIFO) context = self.context while getattr(context, '__parent__', None) is not None: if ISiteRoot.providedBy(context): break r.append(context) context = context.__parent__ titles = [o.Title() for o in reversed(r)] return u'%s - %s' % (' / '.join(titles).encode('utf-8'), self.title) def pas_group(self): return (self._groupname(), self._grouptitle()) def _get_user(self, username): return self.site_members.get(username) def __contains__(self, username): return username in self.keys() def __getitem__(self, username): if username not in self.keys(): raise KeyError('User %s not in group %s (%s)' % ( username, self._groupname(), self._grouptitle(), )) return self._get_user(username) def get(self, username, default=None): if username not in self.keys(): return default return self._get_user(username) # mapping enumeration -- keys/values/items: def keys(self): """ List of login names as group members. This may be cached, as it is expensive to list assigned group principals in the stock Plone group plugin (ZODBGroupManager). """ if self._keys is None: self._keys = self._group.keys() return self._keys # cached lookup for session def values(self): return [self._get_user(k) for k in self.keys()] def items(self): return [(k, self._get_user(k)) for k in self.keys()] def __len__(self): return len(self.keys()) # iterable mapping methods: def iterkeys(self): return iter(self.keys()) __iter__ = iterkeys def itervalues(self): return itertools.imap(self._get_user, self.keys()) def iteritems(self): func = lambda username: (username, self._get_user(username)) # (k,v) return itertools.imap(func, self.keys()) # add / delete (assign/unassign) methods: def add(self, username): if username not in self.site_members: raise RuntimeError('User %s unknown to site' % username) if username not in self.keys(): self._group.assign(username) self.refresh() # need to invalidate keys -- membership modified. def unassign(self, username): if username not in self.keys(): raise ValueError('user %s is not group member' % username) self._group.unassign(username) self.refresh() # need to invalidate keys -- membership modified. def refresh(self): self._keys = None # invalidate previous cached keys self._group.refresh() if interfaces.IWorkspaceGroup.providedBy(self.__parent__): if self.__parent__.baseid == self.baseid: # group equivalence, invalidate parent group too! self.__parent__._keys = None