| Index: appengine/monorail/project/project_helpers.py
|
| diff --git a/appengine/monorail/project/project_helpers.py b/appengine/monorail/project/project_helpers.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..203b0f2541740f11ede10d10c78d282b0bc59469
|
| --- /dev/null
|
| +++ b/appengine/monorail/project/project_helpers.py
|
| @@ -0,0 +1,174 @@
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is govered by a BSD-style
|
| +# license that can be found in the LICENSE file or at
|
| +# https://developers.google.com/open-source/licenses/bsd
|
| +
|
| +"""Helper functions and classes used by the project pages."""
|
| +
|
| +import logging
|
| +import re
|
| +
|
| +import settings
|
| +from framework import framework_bizobj
|
| +from framework import framework_views
|
| +from project import project_views
|
| +from proto import project_pb2
|
| +
|
| +
|
| +_RE_EMAIL_SEPARATORS = re.compile(r'\s|,|;')
|
| +
|
| +
|
| +def BuildProjectMembers(cnxn, project, user_service):
|
| + """Gather data for the members section of a project page.
|
| +
|
| + Args:
|
| + cnxn: connection to SQL database.
|
| + project: Project PB of current project.
|
| + user_service: an instance of UserService for user persistence.
|
| +
|
| + Returns:
|
| + A dictionary suitable for use with EZT.
|
| + """
|
| + # First, get all needed info on all users in one batch of requests.
|
| + users_by_id = framework_views.MakeAllUserViews(
|
| + cnxn, user_service, framework_bizobj.AllProjectMembers(project))
|
| +
|
| + # Second, group the user proxies by role for display.
|
| + owner_proxies = [users_by_id[owner_id]
|
| + for owner_id in project.owner_ids]
|
| + committer_proxies = [users_by_id[committer_id]
|
| + for committer_id in project.committer_ids]
|
| + contributor_proxies = [users_by_id[contrib_id]
|
| + for contrib_id in project.contributor_ids]
|
| +
|
| + return {
|
| + 'owners': owner_proxies,
|
| + 'committers': committer_proxies,
|
| + 'contributors': contributor_proxies,
|
| + 'all_members': users_by_id.values(),
|
| + }
|
| +
|
| +
|
| +def BuildProjectAccessOptions(project):
|
| + """Return a list of project access values for use in an HTML menu.
|
| +
|
| + Args:
|
| + project: current Project PB, or None when creating a new project.
|
| +
|
| + Returns:
|
| + A list of ProjectAccessView objects that can be used in EZT.
|
| + """
|
| + access_levels = [project_pb2.ProjectAccess.ANYONE,
|
| + project_pb2.ProjectAccess.MEMBERS_ONLY]
|
| + access_views = []
|
| + for access in access_levels:
|
| + # Offer the allowed access levels. When editing an existing project,
|
| + # its current access level may always be kept, even if it is no longer
|
| + # in the list of allowed access levels for new projects.
|
| + if (access in settings.allowed_access_levels or
|
| + (project and access == project.access)):
|
| + access_views.append(project_views.ProjectAccessView(access))
|
| +
|
| + return access_views
|
| +
|
| +
|
| +def ParseUsernames(cnxn, user_service, usernames_text):
|
| + """Parse all usernames from a text field and return a list of user IDs.
|
| +
|
| + Args:
|
| + cnxn: connection to SQL database.
|
| + user_service: an instance of UserService for user persistence.
|
| + usernames_text: string that the user entered into a form field for a list
|
| + of email addresses. Or, None if the browser did not send that value.
|
| +
|
| + Returns:
|
| + A set of user IDs for the users named. Or, an empty set if the
|
| + usernames_field was not in post_data.
|
| + """
|
| + if not usernames_text: # The user did not enter any addresses.
|
| + return set()
|
| +
|
| + email_list = _RE_EMAIL_SEPARATORS.split(usernames_text)
|
| + # skip empty strings between consecutive separators
|
| + email_list = [email for email in email_list if email]
|
| +
|
| + id_dict = user_service.LookupUserIDs(cnxn, email_list, autocreate=True)
|
| + return set(id_dict.values())
|
| +
|
| +
|
| +def ParseProjectAccess(project, access_num_str):
|
| + """Parse and validate the "access" field out of post_data.
|
| +
|
| + Args:
|
| + project: Project PB for the project that was edited, or None if the
|
| + user is creating a new project.
|
| + access_num_str: string of digits from the users POST that identifies
|
| + the desired project access level. Or, None if that widget was not
|
| + offered to the user.
|
| +
|
| + Returns:
|
| + An enum project access level, or None if the user did not specify
|
| + any value or if the value specified was invalid.
|
| + """
|
| + access = None
|
| + if access_num_str:
|
| + access_number = int(access_num_str)
|
| + available_access_levels = BuildProjectAccessOptions(project)
|
| + allowed_access_choices = [access_view.key for access_view
|
| + in available_access_levels]
|
| + if access_number in allowed_access_choices:
|
| + access = project_pb2.ProjectAccess(access_number)
|
| +
|
| + return access
|
| +
|
| +
|
| +def MembersWithout(project, exclude_ids):
|
| + """Return three lists of member user IDs, with member_ids not in them."""
|
| + owner_ids = [user_id for user_id in project.owner_ids
|
| + if user_id not in exclude_ids]
|
| + committer_ids = [user_id for user_id in project.committer_ids
|
| + if user_id not in exclude_ids]
|
| + contributor_ids = [user_id for user_id in project.contributor_ids
|
| + if user_id not in exclude_ids]
|
| +
|
| + return owner_ids, committer_ids, contributor_ids
|
| +
|
| +
|
| +def MembersWith(project, new_member_ids, role):
|
| + """Return three lists of member IDs with the new IDs in the right one.
|
| +
|
| + Args:
|
| + project: Project PB for the project to get current members from.
|
| + new_member_ids: set of user IDs for members being added.
|
| + role: string name of the role that new_member_ids should be granted.
|
| +
|
| + Returns:
|
| + Three lists of member IDs with new_member_ids added to the appropriate
|
| + list and removed from any other role.
|
| +
|
| + Raises:
|
| + ValueError: if the role is not one of owner, committer, or contributor.
|
| + """
|
| + owner_ids, committer_ids, contributor_ids = MembersWithout(
|
| + project, new_member_ids)
|
| +
|
| + if role == 'owner':
|
| + owner_ids.extend(new_member_ids)
|
| + elif role == 'committer':
|
| + committer_ids.extend(new_member_ids)
|
| + elif role == 'contributor':
|
| + contributor_ids.extend(new_member_ids)
|
| + else:
|
| + raise ValueError()
|
| +
|
| + return owner_ids, committer_ids, contributor_ids
|
| +
|
| +
|
| +def UsersInvolvedInProject(project):
|
| + """Return a set of all user IDs referenced in the Project."""
|
| + result = set()
|
| + result.update(project.owner_ids)
|
| + result.update(project.committer_ids)
|
| + result.update(project.contributor_ids)
|
| + result.update([perm.member_id for perm in project.extra_perms])
|
| + return result
|
|
|