예제 #1
0
def _BuildRestrictionChoices(project, freq_restrictions, actions):
  """Return a list of autocompletion choices for restriction labels.

  Args:
    project: Project PB for the current project.
    freq_restrictions: list of (action, perm, doc) tuples for restrictions
        that are frequently used.
    actions: list of strings for actions that are relevant to the current
      artifact.

  Returns:
    A list of dictionaries [{'name': 'perm name', 'doc': 'docstring'}, ...]
    suitable for use in a JSON feed to our JS autocompletion functions.
  """
  custom_permissions = permissions.GetCustomPermissions(project)
  choices = []

  for action, perm, doc in freq_restrictions:
    choices.append({
        'name': 'Restrict-%s-%s' % (action, perm),
        'doc': doc,
        })

  for action in actions:
    for perm in custom_permissions:
      choices.append({
          'name': 'Restrict-%s-%s' % (action, perm),
          'doc': 'Permission %s needed to use %s' % (perm, action),
          })

  return choices
예제 #2
0
    def GetCustomPermissions(self, mc, request):
        """Return the custom permissions for the given project."""
        project = self._GetProject(mc, request)
        custom_permissions = permissions.GetCustomPermissions(project)

        result = projects_pb2.GetCustomPermissionsResponse(
            permissions=custom_permissions)
        return result
예제 #3
0
    def GetLabelOptions(self, mc, request):
        """Return the label options for autocomplete for the given project."""
        project = self._GetProject(mc, request)

        with work_env.WorkEnv(mc, self.services) as we:
            config = we.GetProjectConfig(project.project_id)

        label_options = tracker_helpers.GetLabelOptions(
            config, permissions.GetCustomPermissions(project))
        label_defs = [
            project_objects_pb2.LabelDef(label=label['name'],
                                         docstring=label['doc'])
            for label in label_options
        ]

        result = projects_pb2.GetLabelOptionsResponse(
            label_options=label_defs,
            exclusive_label_prefixes=config.exclusive_label_prefixes)
        return result
예제 #4
0
  def HandleRequest(self, mr):
    """Provide the UI with info used in auto-completion.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format
    """
    # Issue options data can be cached separately in each user's browser.  When
    # the project changes, a new cached_content_timestamp is set and it will
    # cause new requests to use a new URL.
    self.SetCacheHeaders(self.response)

    member_data = project_helpers.BuildProjectMembers(
        mr.cnxn, mr.project, self.services.user)
    owner_views = member_data['owners']
    committer_views = member_data['committers']
    contributor_views = member_data['contributors']

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    open_statuses = []
    closed_statuses = []
    for wks in config.well_known_statuses:
      if not wks.deprecated:
        item = dict(name=wks.status, doc=wks.status_docstring)
        if wks.means_open:
          open_statuses.append(item)
        else:
          closed_statuses.append(item)

    # TODO(jrobbins): restrictions on component definitions?
    components = [{'name': cd.path, 'doc': cd.docstring}
                  for cd in config.component_defs if not cd.deprecated]

    labels = []
    field_names = [
        fd.field_name for fd in config.field_defs if not fd.is_deleted]
    non_masked_labels = tracker_helpers.LabelsNotMaskedByFields(
        config, field_names)
    for wkl in non_masked_labels:
      if not wkl.commented:
        item = dict(name=wkl.name, doc=wkl.docstring)
        labels.append(item)

    # TODO(jrobbins): omit fields that they don't have permission to view.
    field_def_views = [
        tracker_views.FieldDefView(fd, config)
        for fd in config.field_defs
        if not fd.is_deleted]
    fields = [
        dict(field_name=fdv.field_name, field_type=fdv.field_type,
             field_id=fdv.field_id, needs_perm=fdv.needs_perm,
             is_required=fdv.is_required, is_multivalued=fdv.is_multivalued,
             choices=[dict(name=c.name, doc=c.docstring) for c in fdv.choices],
             docstring=fdv.docstring)
        for fdv in field_def_views]

    frequent_restrictions = _FREQUENT_ISSUE_RESTRICTIONS[:]
    custom_permissions = permissions.GetCustomPermissions(mr.project)
    if not custom_permissions:
      frequent_restrictions.extend(
          _EXAMPLE_ISSUE_RESTRICTIONS)

    labels.extend(_BuildRestrictionChoices(
        mr.project, frequent_restrictions,
        permissions.STANDARD_ISSUE_PERMISSIONS))

    group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups(
        mr.cnxn, [mem.user_id for mem in member_data['all_members']])
    logging.info('group_ids is %r', group_ids)

    acexclusion_ids = self.services.project.GetProjectAutocompleteExclusion(
        mr.cnxn, mr.project_id)

    # TODO(jrobbins): Normally, users will be allowed view the members
    # of any user group if the project From: email address is listed
    # as a group member, as well as any group that they are personally
    # members of.
    member_ids, owner_ids = self.services.usergroup.LookupVisibleMembers(
        mr.cnxn, group_ids, mr.perms, mr.auth.effective_ids, self.services)
    indirect_ids = set()
    for gid in group_ids:
      indirect_ids.update(member_ids.get(gid, []))
      indirect_ids.update(owner_ids.get(gid, []))
    indirect_user_ids = list(indirect_ids)
    indirect_member_views = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, indirect_user_ids).values()

    visible_member_views = _FilterMemberData(
        mr, owner_views, committer_views, contributor_views,
        indirect_member_views)
    # Filter out servbice accounts
    visible_member_views = [m for m in visible_member_views
                            if not framework_helpers.IsServiceAccount(m.email)
                            and not m.user_id in acexclusion_ids]
    visible_member_email_list = list({
        uv.email for uv in visible_member_views})
    user_indexes = {email: idx
                    for idx, email in enumerate(visible_member_email_list)}
    visible_members_dict = {}
    for uv in visible_member_views:
      visible_members_dict[uv.email] = uv.user_id
    group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups(
        mr.cnxn, visible_members_dict.values())

    for field_dict in fields:
      needed_perm = field_dict['needs_perm']
      if needed_perm:
        qualified_user_indexes = []
        for uv in visible_member_views:
          # TODO(jrobbins): Similar code occurs in field_helpers.py.
          user = self.services.user.GetUser(mr.cnxn, uv.user_id)
          auth = monorailrequest.AuthData.FromUserID(
              mr.cnxn, uv.user_id, self.services)
          user_perms = permissions.GetPermissions(
              user, auth.effective_ids, mr.project)
          has_perm = user_perms.CanUsePerm(
              needed_perm, auth.effective_ids, mr.project, [])
          if has_perm:
            qualified_user_indexes.append(user_indexes[uv.email])

        field_dict['user_indexes'] = sorted(set(qualified_user_indexes))

    excl_prefixes = [prefix.lower() for prefix in
                     config.exclusive_label_prefixes]
    members_def_list = [dict(name=email, doc='')
                        for email in visible_member_email_list]
    members_def_list = sorted(
        members_def_list, key=lambda md: md['name'])
    for md in members_def_list:
      md_id = visible_members_dict[md['name']]
      if md_id in group_ids:
        md['is_group'] = True

    return {
        'open': open_statuses,
        'closed': closed_statuses,
        'statuses_offer_merge': config.statuses_offer_merge,
        'components': components,
        'labels': labels,
        'fields': fields,
        'excl_prefixes': excl_prefixes,
        'strict': ezt.boolean(config.restrict_to_known),
        'members': members_def_list,
        'custom_permissions': custom_permissions,
        }