Exemple #1
0
def all_workspace_users(site):
    """return a set of all workspace users"""
    r = set()
    all_workspaces = get_workspaces(site)
    for workspace in all_workspaces:
        roster = IWorkspaceRoster(workspace)
        r.update(roster.keys())
    return r
Exemple #2
0
def all_workspace_users(site):
    """return a set of all workspace users"""
    r = set()
    all_workspaces = get_workspaces(site)
    for workspace in all_workspaces:
        roster = IWorkspaceRoster(workspace)
        r.update(roster.keys())
    return r
def other_users(project):
    """
    Given project, get de-duped list of users who are neither form
    users nor project managers.
    """
    form_users = set(merged_form_users(project))
    managers = set(IWorkspaceRoster(project).groups['managers'].keys())
    all_users = set(IWorkspaceRoster(project).keys())
    return ((all_users - managers) - form_users)
 def add_project(self, id, title=None):
     project = self.add_check(PROJECT_TYPE, id, IProject, Project)
     members = ISiteMembers(self.portal)
     if self.TEST_MEMBER not in members:
         members.register(self.TEST_MEMBER, send=False)
     assert self.TEST_MEMBER in members
     roster = IWorkspaceRoster(project)
     roster.add(self.TEST_MEMBER)
     assert self.TEST_MEMBER in roster
     return project
 def update(self, *args, **kwargs):
     self.roster = IWorkspaceRoster(self.context)
     if 'confirm_purge' in self.request.form:
         username = self.request.form.get('purgeuser').strip()
         if username not in self.roster:
             raise ValueError('User name for purge not found %s' % username)
         if not self.roster.can_purge(username):
             raise ValueError('User name %s locked from purging.' %
                              username)
         self.roster.purge_user(username)
Exemple #6
0
 def add_project(self, id, title=None):
     project = self.add_check(PROJECT_TYPE, id, IProject, Project)
     members = ISiteMembers(self.portal)
     if self.TEST_MEMBER not in members:
         members.register(self.TEST_MEMBER, send=False)
     assert self.TEST_MEMBER in members
     roster = IWorkspaceRoster(project)
     roster.add(self.TEST_MEMBER)
     assert self.TEST_MEMBER in roster
     return project
Exemple #7
0
def user_workspaces(username, context=None, finder=get_workspaces):
    """
    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.

    A workspace enumerator/finder other than get_workspaces() may be passed
    (e.g. collective.teamwork.utils.get_projects).
    """
    suffix = '-viewers'
    site = getSite()
    context = context or site
    # get all PAS groups for workspaces contained within context:
    all_workspaces = finder(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))
Exemple #8
0
 def test_unassign_contained_secondary(self):
     """Unassign from workgroup, removed from secondary contained"""
     project, roster = self._base_fixtures()
     team = project['team1']
     team_roster = IWorkspaceRoster(team)
     username = '******'
     self.site_members.register(username, send=False)
     roster.add(username)
     team_roster.add(username)
     team_roster.groups['managers'].add(username)
     self.assertIn(username, roster)
     self.assertIn(username, team_roster)
     self.assertIn(username, team_roster.groups['managers'])
     roster.unassign(username)
     self.assertNotIn(username, roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, team_roster.groups['managers'])
 def test_unassign_contained_secondary(self):
     """Unassign from workgroup, removed from secondary contained"""
     project, roster = self._base_fixtures()
     team = project['team1']
     team_roster = IWorkspaceRoster(team)
     username = '******'
     self.site_members.register(username, send=False)
     roster.add(username)
     team_roster.add(username)
     team_roster.groups['managers'].add(username)
     self.assertIn(username, roster)
     self.assertIn(username, team_roster)
     self.assertIn(username, team_roster.groups['managers'])
     roster.unassign(username)
     self.assertNotIn(username, roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, team_roster.groups['managers'])
 def _base_fixtures(self):
     """
     Simple membership, workspace, and roster fixture, for DRY reasons.
     """
     if not getattr(self, '_workspace', None):
         self._workspace = self.portal['project1']
     if not getattr(self, '_roster', None):
         self._roster = IWorkspaceRoster(self._workspace)
     return (self._workspace, self._roster)
Exemple #11
0
 def update(self, *args, **kwargs):
     self.roster = IWorkspaceRoster(self.context)
     if "confirm_purge" in self.request.form:
         username = self.request.form.get("purgeuser").strip()
         if username not in self.roster:
             raise ValueError("User name for purge not found %s" % username)
         if not self.roster.can_purge(username):
             raise ValueError("User name %s locked from purging." % username)
         self.roster.purge_user(username)
 def __init__(self, context, request):
     if not IWorkspaceContext.providedBy(context):
         raise ValueError('Context not a workspace')
     self.context = context
     self.request = request
     self.portal = getSite()
     self._members = ISiteMembers(self.portal)
     self._roster = IWorkspaceRoster(self.context)
     self._mtool = getToolByName(self.portal, 'portal_membership')
     self._secmgr = None
def merged_form_users(project):
    """
    Given a project, get de-duped set of form users from all
    contained workspaces, not including managers at root of the
    project.
    """
    workspaces = all_workspaces(project)
    _form_users = [form_users(w) for w in workspaces]
    merged = set(reduce(lambda a, b: set(a) | set(b), _form_users))
    exclude = set(IWorkspaceRoster(project).groups['managers'].keys())
    return list(merged - exclude)
Exemple #14
0
 def test_can_purge(self):
     """Testing IWorkspaceRoster.can_purge()"""
     project1, roster1 = self._base_fixtures()
     project2 = self.portal['project2']
     roster2 = IWorkspaceRoster(project2)
     user_oneproject = '*****@*****.**'
     user_twoprojects = '*****@*****.**'
     self.site_members.register(user_oneproject, send=False)
     self.site_members.register(user_twoprojects, send=False)
     roster1.add(user_oneproject)
     roster1.add(user_twoprojects)
     roster2.add(user_twoprojects)
     self.assertTrue(roster1.can_purge(user_oneproject))
     self.assertFalse(roster1.can_purge(user_twoprojects))  # disallowed
     self.assertFalse(roster2.can_purge(user_twoprojects))  # here too.
     self.assertFalse(roster2.can_purge(user_oneproject))  # not in here
     # cannot purge from a team, even with otherwise purgeable user:
     self.assertFalse(
         IWorkspaceRoster(project1['team1']).can_purge(user_oneproject)
         )
Exemple #15
0
def fix_current_user(context):
    """
    When a project is added, the current user context may not yet
    have Manager role added to the generated user object, even if the
    user is technically a member of the group.  This is only an issue
    when we attempt to do something requiring a group membership added
    in the same transation.  This is a workaround.
    """
    current = ISiteMembers(getSite()).current()
    roster = IWorkspaceRoster(context)
    manager_group = roster.groups.get('managers').pas_group()[0]
    current._addGroups((manager_group,))
Exemple #16
0
class PurgeUserView(WorkspaceViewBase):
    """View to purge a single user from project"""

    def __init__(self, context, request):
        if not IProjectContext.providedBy(context):
            raise ValueError("Can only purge from top-level projects")
        super(PurgeUserView, self).__init__(context, request)

    def update(self, *args, **kwargs):
        self.roster = IWorkspaceRoster(self.context)
        if "confirm_purge" in self.request.form:
            username = self.request.form.get("purgeuser").strip()
            if username not in self.roster:
                raise ValueError("User name for purge not found %s" % username)
            if not self.roster.can_purge(username):
                raise ValueError("User name %s locked from purging." % username)
            self.roster.purge_user(username)

    def __call__(self, *args, **kwargs):
        self.update(*args, **kwargs)
        return self.index(*args, **kwargs)  # form template
Exemple #17
0
 def test_purge_exceptions(self):
     """Test for expected failure on disallowed purge of user"""
     project1, roster1 = self._base_fixtures()
     project2 = self.portal['project2']
     roster2 = IWorkspaceRoster(project2)
     username = '******'
     self.site_members.register(username, send=False)
     roster1.add(username)
     roster2.add(username)
     # user cannot be purged because of membership elsewhere:
     self.assertRaises(
         RuntimeError,
         roster2.purge_user,
         username,
         )
     # user not in roster
     self.assertRaises(
         RuntimeError,
         roster2.purge_user,
         '*****@*****.**',
         )
 def test_purge_exceptions(self):
     """Test for expected failure on disallowed purge of user"""
     project1, roster1 = self._base_fixtures()
     project2 = self.portal['project2']
     roster2 = IWorkspaceRoster(project2)
     username = '******'
     self.site_members.register(username, send=False)
     roster1.add(username)
     roster2.add(username)
     # user cannot be purged because of membership elsewhere:
     self.assertRaises(
         RuntimeError,
         roster2.purge_user,
         username,
     )
     # user not in roster
     self.assertRaises(
         RuntimeError,
         roster2.purge_user,
         '*****@*****.**',
     )
class PurgeUserView(WorkspaceViewBase):
    """View to purge a single user from project"""
    def __init__(self, context, request):
        if not IProjectContext.providedBy(context):
            raise ValueError('Can only purge from top-level projects')
        super(PurgeUserView, self).__init__(context, request)

    def update(self, *args, **kwargs):
        self.roster = IWorkspaceRoster(self.context)
        if 'confirm_purge' in self.request.form:
            username = self.request.form.get('purgeuser').strip()
            if username not in self.roster:
                raise ValueError('User name for purge not found %s' % username)
            if not self.roster.can_purge(username):
                raise ValueError('User name %s locked from purging.' %
                                 username)
            self.roster.purge_user(username)

    def __call__(self, *args, **kwargs):
        self.update(*args, **kwargs)
        return self.index(*args, **kwargs)  # form template
Exemple #20
0
class RosterView(object):
    def __init__(self, context, request):
        self.context = context
        self.request = request
        self.roster = None  # to be set in self.update()

    def update(self):
        self.roster = IWorkspaceRoster(self.context)
        self.members = self.roster.values()  # list of IPropertiedUser objects

    def __call__(self, *args, **kwargs):
        self.update(*args, **kwargs)
        return self.index(*args, **kwargs)
 def test_assign_unassign_recursive(self):
     """Unassigning user from project removes from contained workspaces"""
     workspace, roster = self._base_fixtures()
     username = '******'
     self.site_members.register(username, send=False)
     project, project_roster = self._base_fixtures()
     team = project['team1']
     team_roster = IWorkspaceRoster(team)
     subteam = team['subteam']
     subteam_roster = IWorkspaceRoster(subteam)
     self.assertNotIn(username, project_roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, subteam_roster)
     # add recursively adds to parent workspaces, walking upward:
     subteam_roster.add(username)
     self.assertIn(username, subteam_roster)
     self.assertIn(username, team_roster)
     self.assertIn(username, project_roster)
     # remove recursively removes from contained workspaces:
     project_roster.unassign(username)
     self.assertNotIn(username, project_roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, subteam_roster)
Exemple #22
0
 def test_assign_unassign_recursive(self):
     """Unassigning user from project removes from contained workspaces"""
     workspace, roster = self._base_fixtures()
     username = '******'
     self.site_members.register(username, send=False)
     project, project_roster = self._base_fixtures()
     team = project['team1']
     team_roster = IWorkspaceRoster(team)
     subteam = team['subteam']
     subteam_roster = IWorkspaceRoster(subteam)
     self.assertNotIn(username, project_roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, subteam_roster)
     # add recursively adds to parent workspaces, walking upward:
     subteam_roster.add(username)
     self.assertIn(username, subteam_roster)
     self.assertIn(username, team_roster)
     self.assertIn(username, project_roster)
     # remove recursively removes from contained workspaces:
     project_roster.unassign(username)
     self.assertNotIn(username, project_roster)
     self.assertNotIn(username, team_roster)
     self.assertNotIn(username, subteam_roster)
class RosterView(object):

    def __init__(self, context, request):
        self.context = context
        self.request = request
        self.roster = None  # to be set in self.update()

    def update(self):
        self.roster = IWorkspaceRoster(self.context)
        self.members = self.roster.values()  # list of IPropertiedUser objects

    def __call__(self, *args, **kwargs):
        self.update(*args, **kwargs)
        return self.index(*args, **kwargs)
 def update(self, *args, **kwargs):
     # get list of IPropertiedUser objects for all members
     members = IWorkspaceRoster(self.context).values()
     self._update_schema(members)
     self.info = map(self._info, members)
     self.output = StringIO()
     self.output.write(u'\ufeff'.encode('utf8'))  # UTF-8 BOM for MSExcel
     self.writer = csv.DictWriter(
         self.output,
         self.schemakeys,
         extrasaction='ignore',
         )
     # write heading row:
     self.writer.writerow(dict([(n, n) for n in self.schemakeys]))
     for record in self.info:
         self.writer.writerow(record)
     self.output.seek(0)
 def test_can_purge(self):
     """Testing IWorkspaceRoster.can_purge()"""
     project1, roster1 = self._base_fixtures()
     project2 = self.portal['project2']
     roster2 = IWorkspaceRoster(project2)
     user_oneproject = '*****@*****.**'
     user_twoprojects = '*****@*****.**'
     self.site_members.register(user_oneproject, send=False)
     self.site_members.register(user_twoprojects, send=False)
     roster1.add(user_oneproject)
     roster1.add(user_twoprojects)
     roster2.add(user_twoprojects)
     self.assertTrue(roster1.can_purge(user_oneproject))
     self.assertFalse(roster1.can_purge(user_twoprojects))  # disallowed
     self.assertFalse(roster2.can_purge(user_twoprojects))  # here too.
     self.assertFalse(roster2.can_purge(user_oneproject))  # not in here
     # cannot purge from a team, even with otherwise purgeable user:
     self.assertFalse(
         IWorkspaceRoster(project1['team1']).can_purge(user_oneproject))
def report_main(site, datestamp, perproject=False):
    """
    Given site and datestamp for snapshot, append report result to
    file named project_users.csv with column format:

    month, date, project_name, #users, #managers, #teams, #forms.
    """
    if DETAIL_DEBUG:
        print '###### SITE REPORT DETAIL: %s ######' % site.getId()

    catalog = getToolByName(site, 'portal_catalog')
    r = catalog.unrestrictedSearchResults(
        {'object_provides': IProjectContext.__identifier__})
    projects = [brain._unrestrictedGetObject() for brain in r]
    if not os.path.isdir(DIRNAME):
        os.mkdir(DIRNAME)
    columns = (
        'month',
        'date',
        'all_users',
        'managers',
        'form_users',
        'other_users',
        'project_count',
        'team_count',
    )
    sitesnap = ProjectSnapshot(
        name='site-%s' % site.getId(),
        title=_u(site.Title()),
        date=datestamp,
        month=MONTHS.get(datestamp.month),
    )
    sitesnap.project_count = 0
    sitesnap.team_count = 0
    site_filename = os.path.join(DIRNAME, '%s.csv' % sitesnap.name)
    if os.path.exists(site_filename):
        out = open(site_filename, 'r')
        data = out.readlines()
        out.close()
        if any([(str(datestamp) in line) for line in data]):
            return  # already have site report for date, done with this site
        site_out = open(site_filename, 'a')  # append to EOF
    else:
        site_out = open(site_filename, 'w')  # will create
        site_out.write('%s\n' % ','.join(columns))  # new file, ergo headings
    for project in projects:
        sitesnap.project_count += 1
        roster = IWorkspaceRoster(project)
        snapshot = ProjectSnapshot(
            name=project.getId(),
            title=_u(project.Title()),
        )
        snapshot.project_count = 1
        snapshot.date = datestamp
        snapshot.month = MONTHS.get(datestamp.month)
        snapshot.all_users = set(filtered_users(roster))
        sitesnap.all_users = sitesnap.all_users.union(snapshot.all_users)
        snapshot.other_users = set(filtered_users(other_users(project)))
        snapshot.managers = set(
            filtered_users(roster.groups['managers'].keys()))
        sitesnap.managers = sitesnap.managers.union(snapshot.managers)
        snapshot.form_users = set(filtered_users(merged_form_users(project)))
        sitesnap.form_users = sitesnap.form_users.union(snapshot.form_users)
        snapshot.team_count = len(all_workspaces(project)) - 1
        sitesnap.team_count += snapshot.team_count
        if DETAIL_DEBUG:
            print '== PROJECT: %s ==' % project.getId()
            print '  Team workspace count: %s' % snapshot.team_count
            print '  Total users (all categories): %s' % len(
                snapshot.all_users)
            print '   Managers of project: %s' % len(snapshot.managers)
            for email in snapshot.managers:
                print '\t   - %s' % email
            print '   Form entry users, incl. team managers who are not project managers: %s' % len(
                snapshot.form_users)
            for email in snapshot.form_users:
                print '\t   - %s' % email
            print '   Other users (not managers, not form entry): %s' % len(
                snapshot.other_users)
            for email in snapshot.other_users:
                print '\t   - %s' % email

        if perproject:
            proj_filename = os.path.join(
                DIRNAME, '%s-%s.csv' % (
                    site.getId(),
                    project.getId(),
                ))
            if os.path.exists(proj_filename):
                out = open(proj_filename, 'r')
                data = out.readlines()  # existing data in file
                out.close()
                if any([(str(datestamp) in line) for line in data]):
                    continue  # don't duplicate entry for date already in file
                out = open(proj_filename, 'a')  # append to EOF
            else:
                out = open(proj_filename, 'w')  # will create
                out.write('%s\n' % ','.join(columns))  # new file -> headings
            writer = csv.DictWriter(out, columns, extrasaction='ignore')
            # write row to CSV from snapshot, convert u'' to utf-8 as needed
            writer.writerow(
                dict([(k, output_value(k, v))
                      for k, v in snapshot.__dict__.items()]))
            out.close()

    # now normalize site-wide users for greatest role... if a user is manager
    # in project A, do not include them in form users just because they have
    # form user role in project B:
    sitesnap.form_users = sitesnap.form_users - sitesnap.managers
    sitesnap.other_users = (sitesnap.all_users -
                            sitesnap.managers) - (sitesnap.form_users)
    # final reconciliation, do not include any users in specific lists
    # if not in all_users group:
    sitesnap.form_users = sitesnap.form_users.intersection(sitesnap.all_users)
    sitesnap.managers = sitesnap.managers.intersection(sitesnap.all_users)

    if DETAIL_DEBUG:
        print '== SITE: %s ==' % site.getId()
        print '  Total UNIQUE users (all categories): %s' % len(
            sitesnap.all_users)
        print '   UNIQUE managers of project: %s' % len(sitesnap.managers)
        for email in sitesnap.managers:
            print '\t   - %s' % email
        print '   UNIQUE form entry users, incl. team managers who are not project managers: %s' % len(
            sitesnap.form_users)
        for email in sitesnap.form_users:
            print '\t   - %s' % email
        print '   UNIQUE other users (not managers, not form entry): %s' % len(
            sitesnap.other_users)
        for email in sitesnap.other_users:
            print '\t   - %s' % email

    site_writer = csv.DictWriter(site_out, columns, extrasaction='ignore')
    site_writer.writerow(
        dict([(k, output_value(k, v)) for k, v in sitesnap.__dict__.items()]))
    site_out.close()
Exemple #27
0
 def update(self):
     self.roster = IWorkspaceRoster(self.context)
     self.members = self.roster.values()  # list of IPropertiedUser objects
def form_users(workspace):
    """Given a workspace, get the ids of users with forms role"""
    roster = IWorkspaceRoster(workspace)
    _formusers = set(roster.groups['forms'].keys())
    _leads = set(roster.groups['managers'].keys())
    return list(_formusers | _leads)
 def update(self):
     self.roster = IWorkspaceRoster(self.context)
     self.members = self.roster.values()  # list of IPropertiedUser objects