Example #1
0
def user_workspaces(username, context=None):
    """
    Get workspaces for username, matching only workspaces for which
    the given user is a member; may be given context or use the
    site root as default context.
    """
    suffix = '-viewers'
    site = getSite()
    context = context or site
    # get all PAS groups for workspaces contained within context:
    all_workspaces = get_workspaces(context)
    if not all_workspaces:
        # context contains no workspaces, even if context itself is workspace
        return []
    _pasgroup = lambda g: g.pas_group()
    _wgroups = lambda w: map(_pasgroup, IWorkspaceRoster(w).groups.values())
    local_groups = set(
        zip(*itertools.chain(*map(_wgroups, all_workspaces)))[0]
        )
    if not local_groups:
        return []
    # get all '-viewers' groups user belongs to, intersect with local:
    user = ISiteMembers(site).get(username)
    usergroups = [name for name in user.getGroups() if name.endswith(suffix)]
    considered = [name for name in local_groups.intersection(usergroups)]
    # each considered group (by suffix convention) is always 1:1 with
    # workspaces, no dupes, so we can map those workspaces:
    return map(group_workspace, set(considered))
Example #2
0
def handle_workspace_removal(context, event):
    """Handler for IObjectRemovedEvent on a workspace"""
    site = getSite()
    if site is None:
        return  # in case of recursive plone site removal, ignore
    pasgroups = ISiteMembers(site).groups
    roster = WorkspaceRoster(context)
    for group in roster.groups.values():
        groupname = group.pas_group()[0]
        if groupname in pasgroups:
            pasgroups.remove(groupname)
    # remove group names for nested workspaces (also, by implication,
    #   removed from the PAS group manager plugin).
    for workspace in get_workspaces(context):
        handle_workspace_removal(workspace, event=event)
Example #3
0
def handle_workspace_pasted(context, event, original_path):
    """handle IObjectAddedEvent after a copy/paste opertion"""
    create_workspace_groups_roles(context)
    for workspace in get_workspaces(context):
        create_workspace_groups_roles(workspace)
Example #4
0
 def _update_grid(self, *args, **kwargs):
     groupmeta = self.groups()
     ## create a mapping of named (by group) queues for each action
     ## each mapping will maintain a set of usernames per group
     ## for removal, addition:
     _unassign = dict((info['groupid'], set()) for info in groupmeta)
     _add = dict((info['groupid'], set()) for info in groupmeta)
     ## get a list of known usernames to form at time of its render
     ## -- this avoids race condition when roster changes do to a member
     ##    being added in the meantime; however, if a member is deleted,
     ##    between form render and form submit, we need to handle that
     ##    by getting an intersection of roster for workspace and the
     ##    set of all usernames known to the form.
     ##    (the form template is responsible to render a hidden input
     ##      for each username with a name containing the username).
     known = set(self.roster.keys())
     managed = set(k.replace('managegroups-', '') for k in self.form.keys()
                   if k.startswith('managegroups-'))
     managed = managed.intersection(known)
     ## iterate through each known group (column in grid):
     for info in groupmeta:
         groupid = info['groupid']
         group = self.roster.groups[groupid]
         form_group_users = set(k.split('/')[1] for k, v in self.form.items()
                                if k.startswith('group-%s/' % groupid))
         for username in managed:
             if username not in form_group_users and username in group:
                 # was in group existing, but ommitted/unchecked in form
                 # for this username -- mark for removal.
                 _unassign[groupid].add(username)
             elif username in form_group_users and username not in group:
                 # not yet in existing group, but specified/checked
                 # in form, so we need to mark for adding
                 _add[groupid].add(username)
     groups = self.roster.groups.values()
     for groupid, deletions in _unassign.items():
         group = self.roster.groups[groupid]
         for username in deletions:
             if username in group:
                 existing_user_groups = [g for g in groups
                                         if username in g]
                 if username == self.authuser and groupid == 'managers':
                     msg = u'Managers cannot remove manager role for '\
                           u'themselves (%s)' % (username,)
                     self.status.addStatusMessage(msg, type='warning')
                     continue
                 if groupid == 'viewers' and len(existing_user_groups) > 1:
                     other_deletions = reduce(
                         _true,
                         [username in v for k, v in _unassign.items()
                          if k != 'viewers'],
                         )
                     if not other_deletions:
                         # danger, danger: user in non-viewers group
                         # not also marked for deletion
                         msg = u'User %s cannot be removed from '\
                               u'Viewers group when also member '\
                               u'of other groups.  To remove '\
                               u'use please uncheck all group '\
                               u'assignments in the grid.' % (username,)
                         self.status.addStatusMessage(
                             msg,
                             type="warning",
                             )
                         continue
                 group.unassign(username)
                 rmsg = u'%s removed from %s group for workspace (%s).'
                 msg = rmsg % (
                     username,
                     group.title,
                     self.title,
                     )
                 if groupid == 'viewers':
                     # a total removal from workspace implies removal
                     # of all assignments from contained workspaces.
                     self.status.addStatusMessage(msg, type='info')
                     self._log(msg, level=logging.INFO)
                     for workspace in get_workspaces(self.context):
                         roster = WorkspaceRoster(workspace)
                         if username in roster.groups['viewers']:
                             for group in roster.groups.values():
                                 if username in group:
                                     group.unassign(username)
     for groupid, additions in _add.items():
         group = self.roster.groups[groupid]
         for username in additions:
             if username not in group:
                 group.add(username)
                 msg = u'%s added to %s group for workspace (%s).' % (
                     username,
                     group.title,
                     self.title,
                     )
                 self.status.addStatusMessage(msg, type='info')
                 self._log(msg, level=logging.INFO)
     self.refresh()