Example #1
0
    def PresubmitIssue(self, mc, request):
        """Provide the UI with warnings and suggestions."""
        project, issue, config = self._GetProjectIssueAndConfig(
            mc, request.issue_ref, issue_required=False)

        with mc.profiler.Phase('making user views'):
            try:
                proposed_owner_id = converters.IngestUserRef(
                    mc.cnxn, request.issue_delta.owner_ref, self.services.user)
            except exceptions.NoSuchUserException:
                proposed_owner_id = 0

            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, [proposed_owner_id])
            proposed_owner_view = users_by_id[proposed_owner_id]

        with mc.profiler.Phase('Applying IssueDelta'):
            if issue:
                proposed_issue = copy.deepcopy(issue)
            else:
                proposed_issue = tracker_pb2.Issue(
                    owner_id=framework_constants.NO_USER_SPECIFIED,
                    project_id=config.project_id)
            issue_delta = converters.IngestIssueDelta(
                mc.cnxn,
                self.services,
                request.issue_delta,
                config,
                None,
                ignore_missing_objects=True)
            tracker_bizobj.ApplyIssueDelta(mc.cnxn, self.services.issue,
                                           proposed_issue, issue_delta, config)

        with mc.profiler.Phase('applying rules'):
            _, traces = filterrules_helpers.ApplyFilterRules(
                mc.cnxn, self.services, proposed_issue, config)
            logging.info('proposed_issue is now: %r', proposed_issue)
            logging.info('traces are: %r', traces)

        with mc.profiler.Phase('making derived user views'):
            derived_users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, [proposed_issue.derived_owner_id],
                proposed_issue.derived_cc_ids)
            framework_views.RevealAllEmailsToMembers(mc.auth, project,
                                                     derived_users_by_id)

        with mc.profiler.Phase('pair derived values with rule explanations'):
            (derived_labels, derived_owners, derived_ccs, warnings,
             errors) = (tracker_helpers.PairDerivedValuesWithRuleExplanations(
                 proposed_issue, traces, derived_users_by_id))

        result = issues_pb2.PresubmitIssueResponse(
            owner_availability=proposed_owner_view.avail_message_short,
            owner_availability_state=proposed_owner_view.avail_state,
            derived_labels=converters.ConvertValueAndWhyList(derived_labels),
            derived_owners=converters.ConvertValueAndWhyList(derived_owners),
            derived_ccs=converters.ConvertValueAndWhyList(derived_ccs),
            warnings=converters.ConvertValueAndWhyList(warnings),
            errors=converters.ConvertValueAndWhyList(errors))
        return result
Example #2
0
    def testMakeEmailTasks_Starrer(self):
        """Users who starred the issue are notified iff they opt in."""
        issue = fake.MakeTestIssue(789, 1, 'summary', 'New', 0, issue_id=78901)
        self.services.issue.TestAddIssue(issue)
        now = int(time.time())
        self.SetUpFieldValues(issue, now)
        issue.project_name = 'proj'
        comment = self.MakePingComment()
        next_action_field_def = self.config.field_defs[0]
        pings = [(next_action_field_def, now)]

        starrer_333 = self.services.user.TestAddUser('*****@*****.**',
                                                     333)
        starrer_333.notify_starred_ping = True
        self.services.user.TestAddUser('*****@*****.**', 444)
        starrer_ids = [333, 444]
        users_by_id = framework_views.MakeAllUserViews(
            'fake cnxn', self.services.user,
            [self.owner.user_id, self.date_action_user.user_id], starrer_ids)

        tasks = self.servlet._MakeEmailTasks('fake cnxn', issue, self.project,
                                             self.config, comment, starrer_ids,
                                             'example-app.appspot.com',
                                             users_by_id, pings)
        self.assertEqual(1, len(tasks))
        notify_owner_task = tasks[0]
        self.assertEqual('*****@*****.**', notify_owner_task['to'])
Example #3
0
    def testMakeEmailTasks_Owner(self):
        """The issue owner gets pinged and the email has expected content."""
        issue = fake.MakeTestIssue(789,
                                   1,
                                   'summary',
                                   'New',
                                   self.owner.user_id,
                                   issue_id=78901)
        self.services.issue.TestAddIssue(issue)
        now = int(time.time())
        self.SetUpFieldValues(issue, now)
        issue.project_name = 'proj'
        comment = self.MakePingComment()
        next_action_field_def = self.config.field_defs[0]
        pings = [(next_action_field_def, now)]
        users_by_id = framework_views.MakeAllUserViews(
            'fake cnxn', self.services.user,
            [self.owner.user_id, self.date_action_user.user_id])

        tasks = self.servlet._MakeEmailTasks('fake cnxn', issue, self.project,
                                             self.config, comment, [],
                                             'example-app.appspot.com',
                                             users_by_id, pings)
        self.assertEqual(1, len(tasks))
        notify_owner_task = tasks[0]
        self.assertEqual('*****@*****.**', notify_owner_task['to'])
        self.assertEqual('Follow up on issue 1 in proj: summary',
                         notify_owner_task['subject'])
        body = notify_owner_task['body']
        self.assertIn(comment.content, body)
        self.assertIn(next_action_field_def.docstring, body)
Example #4
0
def convert_approval_amendments(amendments, mar, services):
    """Convert a list of Monorail Amendment PBs API ApprovalUpdate."""
    amendments_user_ids = tracker_bizobj.UsersInvolvedInAmendments(amendments)
    users_by_id = framework_views.MakeAllUserViews(mar.cnxn, services.user,
                                                   amendments_user_ids)
    framework_views.RevealAllEmailsToMembers(mar.auth, mar.project,
                                             users_by_id)

    result = api_pb2_v1.ApprovalUpdate(kind='monorail#approvalCommentUpdate')
    for amendment in amendments:
        if amendment.field == tracker_pb2.FieldID.CUSTOM:
            if amendment.custom_field_name == 'Status':
                status_number = tracker_pb2.ApprovalStatus(
                    amendment.newvalue.upper()).number
                result.status = api_pb2_v1.ApprovalStatus(status_number).name
            elif amendment.custom_field_name == 'Approvers':
                for user_id in amendment.added_user_ids:
                    user_email = _get_user_email(services.user, mar.cnxn,
                                                 user_id)
                    result.approvers.append(user_email)
                for user_id in amendment.removed_user_ids:
                    user_email = _get_user_email(services.user, mar.cnxn,
                                                 user_id)
                    result.approvers.append('-%s' % user_email)
            else:
                fv = api_pb2_v1.FieldValue()
                fv.fieldName = amendment.custom_field_name
                fv.fieldValue = tracker_bizobj.AmendmentString(
                    amendment, users_by_id)
                # TODO(jojwang): monorail:4229, add approvalName field to FieldValue
                result.fieldValues.append(fv)

    return result
Example #5
0
    def GetConfig(self, mc, request):
        """Return the specified project config."""
        project = self._GetProject(mc, request)

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

        with mc.profiler.Phase('making user views'):
            users_involved = tracker_bizobj.UsersInvolvedInConfig(config)
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved)
            framework_views.RevealAllEmailsToMembers(mc.auth, project,
                                                     users_by_id)

            label_ids = tracker_bizobj.LabelIDsInvolvedInConfig(config)
            labels_by_id = {
                label_id:
                self.services.config.LookupLabel(mc.cnxn, config.project_id,
                                                 label_id)
                for label_id in label_ids
            }

        result = converters.ConvertConfig(project, config, users_by_id,
                                          labels_by_id)
        return result
Example #6
0
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(),
    }
Example #7
0
    def GatherPageData(self, mr):
        """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
        page_data = super(AdminRules, self).GatherPageData(mr)
        rules = self.services.features.GetFilterRules(mr.cnxn, mr.project_id)
        users_by_id = framework_views.MakeAllUserViews(
            mr.cnxn, self.services.user,
            [rule.default_owner_id for rule in rules],
            *[rule.add_cc_ids for rule in rules])
        framework_views.RevealAllEmailsToMembers(mr.auth, mr.project,
                                                 users_by_id)
        rule_views = [
            filterrules_views.RuleView(rule, users_by_id) for rule in rules
        ]

        for idx, rule_view in enumerate(rule_views):
            rule_view.idx = idx + 1  # EZT has no loop index, so we set idx.

        page_data.update({
            'rules':
            rule_views,
            'new_rule_indexes':
            (list(range(len(rules) + 1, filterrules_helpers.MAX_RULES + 1))),
            'max_rules':
            filterrules_helpers.MAX_RULES,
        })
        return page_data
Example #8
0
    def ConvertIssueApprovalsTemplate(self, mc, request):
        """Update an issue's existing approvals structure to match the one of the
       given template."""

        if not request.issue_ref.local_id or not request.issue_ref.project_name:
            raise exceptions.InputException('Param `issue_ref.local_id` empty')
        if not request.template_name:
            raise exceptions.InputException('Param `template_name` empty')

        project, issue, config = self._GetProjectIssueAndConfig(
            mc, request.issue_ref, use_cache=False)

        with work_env.WorkEnv(mc, self.services) as we:
            we.ConvertIssueApprovalsTemplate(config,
                                             issue,
                                             request.template_name,
                                             request.comment_content,
                                             send_email=request.send_email)
            related_refs = we.GetRelatedIssueRefs([issue])

        with mc.profiler.Phase('making user views'):
            users_involved_in_issue = tracker_bizobj.UsersInvolvedInIssues(
                [issue])
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved_in_issue)
            framework_views.RevealAllEmailsToMembers(mc.auth, project,
                                                     users_by_id)

        with mc.profiler.Phase('converting to response objects'):
            response = issues_pb2.ConvertIssueApprovalsTemplateResponse()
            response.issue.CopyFrom(
                converters.ConvertIssue(issue, users_by_id, related_refs,
                                        config))
        return response
Example #9
0
    def ListComments(self, mc, request):
        """Return comments on the specified issue in a response proto."""
        project, issue, config = self._GetProjectIssueAndConfig(
            mc, request.issue_ref)
        with work_env.WorkEnv(mc, self.services) as we:
            comments = we.ListIssueComments(issue)
            _, comment_reporters = we.LookupIssueFlaggers(issue)

        with mc.profiler.Phase('making user views'):
            users_involved_in_comments = tracker_bizobj.UsersInvolvedInCommentList(
                comments)
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved_in_comments)
            framework_views.RevealAllEmailsToMembers(mc.auth, project,
                                                     users_by_id)

        with mc.profiler.Phase('converting to response objects'):
            issue_perms = permissions.UpdateIssuePermissions(
                mc.perms, project, issue, mc.auth.effective_ids, config=config)
            converted_comments = converters.ConvertCommentList(
                issue, comments, config, users_by_id, comment_reporters,
                mc.auth.user_id, issue_perms)
            response = issues_pb2.ListCommentsResponse(
                comments=converted_comments)

        return response
Example #10
0
    def ListHotlistsByUser(self, mc, request):
        """Return the hotlists for the given user."""
        user_id = converters.IngestUserRef(mc.cnxn, request.user,
                                           self.services.user)

        with work_env.WorkEnv(mc, self.services) as we:
            mc.LookupLoggedInUserPerms(None)
            hotlists = we.ListHotlistsByUser(user_id)

        with mc.profiler.Phase('making user views'):
            users_involved = features_bizobj.UsersOwnersOfHotlists(hotlists)
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved)
            framework_views.RevealAllEmailsToMembers(mc.auth, None,
                                                     users_by_id)

        converted_hotlists = [
            converters.ConvertHotlist(hotlist, users_by_id)
            for hotlist in hotlists
        ]

        result = features_pb2.ListHotlistsByUserResponse(
            hotlists=converted_hotlists)

        return result
Example #11
0
    def ListHotlistsByIssue(self, mc, request):
        """Return the hotlists the given issue is part of."""
        issue_id = converters.IngestIssueRefs(mc.cnxn, [request.issue],
                                              self.services)[0]

        with work_env.WorkEnv(mc, self.services) as we:
            project = we.GetProjectByName(request.issue.project_name)
            mc.LookupLoggedInUserPerms(project)
            hotlists = we.ListHotlistsByIssue(issue_id)

        with mc.profiler.Phase('making user views'):
            users_involved = features_bizobj.UsersOwnersOfHotlists(hotlists)
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved)
            framework_views.RevealAllEmailsToMembers(mc.auth, None,
                                                     users_by_id)

        converted_hotlists = [
            converters.ConvertHotlist(hotlist, users_by_id)
            for hotlist in hotlists
        ]

        result = features_pb2.ListHotlistsByIssueResponse(
            hotlists=converted_hotlists)

        return result
Example #12
0
def _GetSubscribersAddrPermList(cnxn, services, issue, project, config,
                                omit_addrs, users_by_id):
    """Lookup subscribers, evaluate their saved queries, and decide to notify."""
    users_to_queries = GetNonOmittedSubscriptions(cnxn, services,
                                                  [project.project_id],
                                                  omit_addrs)
    # TODO(jrobbins): need to pass through the user_id to use for "me".
    subscribers_to_notify = EvaluateSubscriptions(cnxn, issue,
                                                  users_to_queries, services,
                                                  config)
    # TODO(jrobbins): expand any subscribers that are user groups.
    subs_needing_user_views = [
        uid for uid in subscribers_to_notify if uid not in users_by_id
    ]
    users_by_id.update(
        framework_views.MakeAllUserViews(cnxn, services.user,
                                         subs_needing_user_views))
    sub_addr_perm_list = ComputeIssueChangeAddressPermList(
        cnxn,
        subscribers_to_notify,
        project,
        issue,
        services,
        omit_addrs,
        users_by_id,
        pref_check_function=lambda *args: True)

    return sub_addr_perm_list
Example #13
0
    def GatherPageData(self, mr):
        if not mr.auth.user_id:
            raise permissions.PermissionException(
                'Anonymous users are not allowed to download hotlist CSV')

        owner_id = mr.hotlist.owner_ids[0]  # only one owner allowed
        users_by_id = framework_views.MakeAllUserViews(mr.cnxn,
                                                       self.services.user,
                                                       [owner_id])
        owner = users_by_id[owner_id]

        # Try to validate XSRF by either user email or user ID.
        try:
            xsrf.ValidateToken(
                mr.token, mr.auth.user_id,
                '/u/%s/hotlists/%s.do' % (owner.email, mr.hotlist.name))
        except xsrf.TokenIncorrect:
            xsrf.ValidateToken(
                mr.token, mr.auth.user_id,
                '/u/%s/hotlists/%s.do' % (owner.user_id, mr.hotlist.name))

        # Sets headers to allow the response to be downloaded.
        self.content_type = 'text/csv; charset=UTF-8'
        download_filename = 'hotlist_%d-issues.csv' % mr.hotlist_id
        self.response.headers.add(
            'Content-Disposition',
            'attachment; filename=%s' % download_filename)
        self.response.headers.add('X-Content-Type-Options', 'nosniff')

        mr.ComputeColSpec(mr.hotlist)
        mr.col_spec = csv_helpers.RewriteColspec(mr.col_spec)
        page_data = hotlistissues.HotlistIssues.GatherPageData(self, mr)
        return csv_helpers.ReformatRowsForCSV(mr, page_data,
                                              '%d/csv' % mr.hotlist_id)
Example #14
0
    def setUp(self):
        self.mox = mox.Mox()
        self.mock_index = self.mox.CreateMockAnything()
        self.mox.StubOutWithMock(search, 'Index')
        self.docs = None
        self.cnxn = 'fake connection'
        self.user_service = fake.UserService()
        self.user_service.TestAddUser('*****@*****.**', 111)
        self.issue_service = fake.IssueService()
        self.config_service = fake.ConfigService()

        self.issue = fake.MakeTestIssue(123, 1, 'test summary', 'New', 111)
        self.issue_service.TestAddIssue(self.issue)
        self.comment = tracker_pb2.IssueComment(
            project_id=789,
            issue_id=self.issue.issue_id,
            user_id=111,
            content='comment content',
            attachments=[
                tracker_pb2.Attachment(filename='hello.c'),
                tracker_pb2.Attachment(filename='hello.h')
            ])
        self.issue_service.TestAddComment(self.comment, 1)
        self.users_by_id = framework_views.MakeAllUserViews(
            self.cnxn, self.user_service, [111])
Example #15
0
    def HandleRequest(self, mr):
        """Process the task to process an issue date action.

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

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
        issue_id = mr.GetPositiveIntParam('issue_id')
        hostport = framework_helpers.GetHostPort()
        issue = self.services.issue.GetIssue(mr.cnxn, issue_id)
        project = self.services.project.GetProject(mr.cnxn, issue.project_id)
        config = self.services.config.GetProjectConfig(mr.cnxn,
                                                       issue.project_id)
        pings = self._CalculateIssuePings(issue, config)
        if not pings:
            logging.warning('Issue %r has no dates to ping afterall?',
                            issue_id)
            return
        comment = self._CreatePingComment(mr.cnxn, issue, pings, hostport)

        users_by_id = framework_views.MakeAllUserViews(
            mr.cnxn, self.services.user,
            tracker_bizobj.UsersInvolvedInIssues([issue]), [comment.user_id])
        logging.info('users_by_id is %r', users_by_id)
        tasks = self._MakeEmailTasks(mr.cnxn, issue, project, config, comment,
                                     hostport, users_by_id, pings)

        notified = notify_helpers.AddAllEmailTasks(tasks)
        return {
            'notified': notified,
        }
Example #16
0
def MakeFieldUserViews(cnxn, template, user_service):
  """Return {user_id: user_view} for users in template field values."""
  field_user_ids = [
      fv.user_id for fv in template.field_values
      if fv.user_id]
  field_user_views = framework_views.MakeAllUserViews(
      cnxn, user_service, field_user_ids)
  return field_user_views
Example #17
0
  def _ProcessUpstreamIssue(
      self, cnxn, upstream_issue, upstream_project, upstream_config,
      issue, omit_ids, hostport, commenter_view):
    """Compute notifications for one upstream issue that is now blocking."""
    upstream_detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, upstream_issue.project_name, urls.ISSUE_DETAIL,
        id=upstream_issue.local_id)
    logging.info('upstream_detail_url = %r', upstream_detail_url)
    detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, issue.project_name, urls.ISSUE_DETAIL,
        id=issue.local_id)

    # Only issues that any contributor could view are sent to mailing lists.
    contributor_could_view = permissions.CanViewIssue(
        set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
        upstream_project, upstream_issue)

    # Now construct the e-mail to send

    # Note: we purposely do not notify users who starred an issue
    # about changes in blocking.
    users_by_id = framework_views.MakeAllUserViews(
        cnxn, self.services.user,
        tracker_bizobj.UsersInvolvedInIssues([upstream_issue]), omit_ids)

    is_blocking = upstream_issue.issue_id in issue.blocked_on_iids

    email_data = {
        'issue': tracker_views.IssueView(
            upstream_issue, users_by_id, upstream_config),
        'summary': upstream_issue.summary,
        'detail_url': upstream_detail_url,
        'is_blocking': ezt.boolean(is_blocking),
        'downstream_issue_ref': tracker_bizobj.FormatIssueRef(
            (None, issue.local_id)),
        'downstream_issue_url': detail_url,
        }

    # TODO(jrobbins): Generate two versions of email body: members
    # vesion has other member full email addresses exposed.  But, don't
    # expose too many as we iterate through upstream projects.
    body_link_only = self.link_only_email_template.GetResponse(
        {'detail_url': upstream_detail_url, 'was_created': ezt.boolean(False)})
    body = self.email_template.GetResponse(email_data)

    omit_addrs = {users_by_id[omit_id].email for omit_id in omit_ids}

    # Get the transitive set of owners and Cc'd users, and their UserView's.
    # Give each user a bullet-list of all the reasons that apply for that user.
    # Starrers are not notified of blocking changes to reduce noise.
    group_reason_list = notify_reasons.ComputeGroupReasonList(
        cnxn, self.services, upstream_project, upstream_issue,
        upstream_config, users_by_id, omit_addrs, contributor_could_view)
    one_issue_email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
        group_reason_list, upstream_issue, body_link_only, body, body,
        upstream_project, hostport, commenter_view, detail_url)

    return one_issue_email_tasks
    def GatherPageData(self, mr):
        """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
        config, component_def = self._GetComponentDef(mr)
        users_by_id = framework_views.MakeAllUserViews(mr.cnxn,
                                                       self.services.user,
                                                       component_def.admin_ids,
                                                       component_def.cc_ids)
        component_def_view = tracker_views.ComponentDefView(
            mr.cnxn, self.services, component_def, users_by_id)
        initial_admins = [
            users_by_id[uid].email for uid in component_def.admin_ids
        ]
        initial_cc = [users_by_id[uid].email for uid in component_def.cc_ids]
        initial_labels = [
            self.services.config.LookupLabel(mr.cnxn, mr.project_id, label_id)
            for label_id in component_def.label_ids
        ]

        creator, created = self._GetUserViewAndFormattedTime(
            mr, component_def.creator_id, component_def.created)
        modifier, modified = self._GetUserViewAndFormattedTime(
            mr, component_def.modifier_id, component_def.modified)

        allow_edit = permissions.CanEditComponentDef(mr.auth.effective_ids,
                                                     mr.perms, mr.project,
                                                     component_def, config)

        subcomponents = tracker_bizobj.FindDescendantComponents(
            config, component_def)
        templates = self.services.config.TemplatesWithComponent(
            mr.cnxn, component_def.component_id, config)
        allow_delete = allow_edit and not subcomponents and not templates

        return {
            'admin_tab_mode': servlet.Servlet.PROCESS_TAB_COMPONENTS,
            'component_def': component_def_view,
            'initial_leaf_name': component_def_view.leaf_name,
            'initial_docstring': component_def.docstring,
            'initial_deprecated': ezt.boolean(component_def.deprecated),
            'initial_admins': initial_admins,
            'initial_cc': initial_cc,
            'initial_labels': initial_labels,
            'allow_edit': ezt.boolean(allow_edit),
            'allow_delete': ezt.boolean(allow_delete),
            'subcomponents': subcomponents,
            'templates': templates,
            'creator': creator,
            'created': created,
            'modifier': modifier,
            'modified': modified,
        }
Example #19
0
    def GatherPageData(self, mr):
        viewed_users_hotlists = self.services.features.GetHotlistsByUserID(
            mr.cnxn, mr.viewed_user_auth.user_id)

        viewed_starred_hids = self.services.hotlist_star.LookupStarredItemIDs(
            mr.cnxn, mr.viewed_user_auth.user_id)
        viewed_users_starred_hotlists, _ = self.services.features.GetHotlistsByID(
            mr.cnxn, viewed_starred_hids)

        viewed_users_relevant_hotlists = viewed_users_hotlists + list(
            set(viewed_users_starred_hotlists.values()) -
            set(viewed_users_hotlists))

        users_by_id = framework_views.MakeAllUserViews(
            mr.cnxn, self.services.user,
            features_bizobj.UsersInvolvedInHotlists(
                viewed_users_relevant_hotlists))

        views = [
            hotlist_views.HotlistView(
                hotlist_pb, mr.auth, mr.viewed_user_auth.user_id, users_by_id,
                self.services.hotlist_star.IsItemStarredBy(
                    mr.cnxn, hotlist_pb.hotlist_id, mr.auth.user_id))
            for hotlist_pb in viewed_users_relevant_hotlists
        ]

        # visible to viewer, not viewed_user
        visible_hotlists = [view for view in views if view.visible]

        owner_of_hotlists = [
            hotlist_view for hotlist_view in visible_hotlists
            if hotlist_view.role_name == 'owner'
        ]
        editor_of_hotlists = [
            hotlist_view for hotlist_view in visible_hotlists
            if hotlist_view.role_name == 'editor'
        ]
        follower_of_hotlists = [
            hotlist_view for hotlist_view in visible_hotlists
            if hotlist_view.role_name == ''
        ]
        starred_hotlists = [
            hotlist_view for hotlist_view in visible_hotlists
            if hotlist_view.hotlist_id in viewed_starred_hids
        ]

        viewed_user_display_name = framework_views.GetViewedUserDisplayName(mr)

        return {
            'user_tab_mode': 'st6',
            'viewed_user_display_name': viewed_user_display_name,
            'owner_of_hotlists': owner_of_hotlists,
            'editor_of_hotlists': editor_of_hotlists,
            'follower_of_hotlists': follower_of_hotlists,
            'starred_hotlists': starred_hotlists,
            'viewing_user_page': ezt.boolean(True),
        }
Example #20
0
 def setUp(self):
     self.cnxn = 'fake sql connection'
     self.services = service_manager.Services(project=fake.ProjectService(),
                                              user=fake.UserService())
     self.services.user.TestAddUser('*****@*****.**', 111)
     self.services.user.TestAddUser('*****@*****.**', 222)
     self.services.user.TestAddUser('*****@*****.**', 333)
     self.users_by_id = framework_views.MakeAllUserViews(
         'cnxn', self.services.user, [111, 222, 333])
     self.effective_ids_by_user = {user: set() for user in {111, 222, 333}}
Example #21
0
  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    if mr.auth.user_id:
      self.services.user.AddVisitedHotlist(
          mr.cnxn, mr.auth.user_id, mr.hotlist_id)

    all_members = (mr.hotlist.owner_ids +
                   mr.hotlist.editor_ids + mr.hotlist.follower_ids)

    hotlist_url = hotlist_helpers.GetURLOfHotlist(
        mr.cnxn, mr.hotlist, self.services.user)

    with self.profiler.Phase('gathering members on this page'):
      users_by_id = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, all_members)
      framework_views.RevealAllEmailsToMembers(mr, users_by_id)

    untrusted_user_group_proxies = []
    # TODO(jojwang): implement FindUntrustedGroups()

    with self.profiler.Phase('making member views'):
      owner_views = self._MakeMemberViews(mr, mr.hotlist.owner_ids, users_by_id)
      editor_views = self._MakeMemberViews(mr, mr.hotlist.editor_ids,
                                           users_by_id)
      follower_views = self._MakeMemberViews(mr, mr.hotlist.follower_ids,
                                             users_by_id)
      all_member_views = owner_views + editor_views + follower_views

    pagination = paginate.ArtifactPagination(
        mr, all_member_views, MEMBERS_PER_PAGE,'%s%s' % (
              hotlist_url, urls.HOTLIST_PEOPLE))

    offer_membership_editing = permissions.CanAdministerHotlist(
        mr.auth.effective_ids, mr.hotlist)

    newly_added_views = [mv for mv in all_member_views
                         if str(mv.user.user_id) in mr.GetParam('new', [])]

    return {
        'is_hotlist': ezt.boolean(True),
        'untrusted_user_groups': untrusted_user_group_proxies,
        'pagination': pagination,
        'initial_add_members': '',
        'subtab_mode': None,
        'initially_expand_form': ezt.boolean(False),
        'newly_added_views': newly_added_views,
        'offer_membership_editing': ezt.boolean(offer_membership_editing),
        'total_num_owners': len(mr.hotlist.owner_ids),
        'check_abandonment': ezt.boolean(True),
        'initial_new_owner_username': '',
        'placeholder': 'new-owner-username',
        'open_dialog': ezt.boolean(False),
        'viewing_user_page': ezt.boolean(True),
        }
Example #22
0
    def GetUser(self, mc, request):
        """Return info about the specified user."""
        with work_env.WorkEnv(mc, self.services) as we:
            users, linked_user_ids = we.ListReferencedUsers(
                [request.user_ref.display_name])
            linked_user_views = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, linked_user_ids)

        with mc.profiler.Phase('converting to response objects'):
            response_users = converters.ConvertUsers(users, linked_user_views)

        return response_users[0]
Example #23
0
def GetVisibleMembers(mr, project, services):
    all_member_ids = framework_bizobj.AllProjectMembers(project)

    all_group_ids = services.usergroup.DetermineWhichUserIDsAreGroups(
        mr.cnxn, all_member_ids)

    (ac_exclusion_ids,
     no_expand_ids) = services.project.GetProjectAutocompleteExclusion(
         mr.cnxn, project.project_id)

    group_ids_to_expand = [
        gid for gid in all_group_ids if gid not in no_expand_ids
    ]

    # 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 = services.usergroup.LookupVisibleMembers(
        mr.cnxn, group_ids_to_expand, mr.perms, mr.auth.effective_ids,
        services)
    indirect_user_ids = set()
    for gids in member_ids.values():
        indirect_user_ids.update(gids)
    for gids in owner_ids.values():
        indirect_user_ids.update(gids)

    visible_member_ids = _FilterMemberData(mr, project.owner_ids,
                                           project.committer_ids,
                                           project.contributor_ids,
                                           indirect_user_ids, project)
    visible_member_ids = _MergeLinkedMembers(mr.cnxn, services.user,
                                             visible_member_ids)

    visible_member_views = framework_views.MakeAllUserViews(
        mr.cnxn, services.user, visible_member_ids, group_ids=all_group_ids)

    # Filter out service accounts
    service_acct_emails = set(
        client_config_svc.GetClientConfigSvc().GetClientIDEmails()[1])
    visible_member_views = {
        m.user_id: m
        for m in visible_member_views.values()
        if not framework_helpers.IsServiceAccount(
            m.email, client_emails=service_acct_emails)
        and not m.user_id in ac_exclusion_ids
    }

    return visible_member_views
Example #24
0
    def GetMemberships(self, mc, request):
        """Return the user groups for the given user visible to the requester."""
        user_id = converters.IngestUserRef(mc.cnxn, request.user_ref,
                                           self.services.user)

        with work_env.WorkEnv(mc, self.services) as we:
            group_ids = we.GetMemberships(user_id)

        with mc.profiler.Phase('converting to response objects'):
            groups_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, group_ids)
            group_refs = converters.ConvertUserRefs(group_ids, [],
                                                    groups_by_id, True)

            return users_pb2.GetMembershipsResponse(group_refs=group_refs)
Example #25
0
  def ListReferencedUsers(self, mc, request):
    """Return the list of existing users in a response proto."""
    emails = request.emails
    if request.user_refs:
      emails = [user_ref.display_name for user_ref in request.user_refs]
    with work_env.WorkEnv(mc, self.services) as we:
      users, linked_user_ids = we.ListReferencedUsers(emails)
      linked_user_views = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, linked_user_ids)

    with mc.profiler.Phase('converting to response objects'):
      response_users = converters.ConvertUsers(users, linked_user_views)
      response = users_pb2.ListReferencedUsersResponse(users=response_users)

    return response
Example #26
0
    def ListHotlistIssues(self, mc, request):
        """Get the issues on the specified hotlist."""
        # TODO(ehmaldonado): This probably doesn't work, since we need to check
        # the permissions for each issue in their own project, and we're not doing
        # that.
        hotlist_id = converters.IngestHotlistRef(mc.cnxn, self.services.user,
                                                 self.services.features,
                                                 request.hotlist_ref)

        with work_env.WorkEnv(mc, self.services) as we:
            hotlist_items = we.GetHotlist(hotlist_id).items
            issue_ids = [item.issue_id for item in hotlist_items]
            issues = we.GetIssuesDict(issue_ids)

            projects = we.GetProjectsByName(
                [issue.project_name for issue in issues.values()])
            configs = we.GetProjectConfigs(
                [project.project_id for project in projects.values()])
            configs = {
                project.project_name: configs[project.project_id]
                for project in projects.values()
            }
            related_refs = we.GetRelatedIssueRefs(iter(issues.values()))

        with mc.profiler.Phase('making user views'):
            users_involved = set(item.adder_id for item in hotlist_items)
            users_involved.update(
                tracker_bizobj.UsersInvolvedInIssues(iter(issues.values())))
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved)
            framework_views.RevealAllEmailsToMembers(mc.auth, None,
                                                     users_by_id)

        hotlist_items = [
            hotlist_item for hotlist_item in hotlist_items
            if hotlist_item.issue_id in issues
        ]

        start, max_items = converters.IngestPagination(request.pagination)
        pagination = paginate.ArtifactPagination(hotlist_items, max_items,
                                                 start, None, None)

        result = features_pb2.ListHotlistIssuesResponse(items=[
            converters.ConvertHotlistItem(hotlist_item, issues, users_by_id,
                                          related_refs, configs)
            for hotlist_item in pagination.visible_results
        ])
        return result
 def setUp(self):
     self.services = service_manager.Services(user=fake.UserService(),
                                              config=fake.ConfigService())
     self.services.user.TestAddUser('*****@*****.**', 111)
     self.services.user.TestAddUser('*****@*****.**', 222)
     self.users_by_id = framework_views.MakeAllUserViews(
         'cnxn', self.services.user, [111, 222])
     self.services.config.TestAddLabelsDict({'Hot': 1, 'Cold': 2})
     self.cd = tracker_bizobj.MakeComponentDef(10,
                                               789,
                                               'UI',
                                               'User interface',
                                               False, [111], [222],
                                               0,
                                               111,
                                               label_ids=[1, 2])
Example #28
0
def convert_amendments(issue, amendments, mar, services):
    """Convert a list of Monorail Amendment PBs to API Update."""
    amendments_user_ids = tracker_bizobj.UsersInvolvedInAmendments(amendments)
    users_by_id = framework_views.MakeAllUserViews(mar.cnxn, services.user,
                                                   amendments_user_ids)
    framework_views.RevealAllEmailsToMembers(mar.auth, mar.project,
                                             users_by_id)

    result = api_pb2_v1.Update(kind='monorail#issueCommentUpdate')
    for amendment in amendments:
        if amendment.field == tracker_pb2.FieldID.SUMMARY:
            result.summary = amendment.newvalue
        elif amendment.field == tracker_pb2.FieldID.STATUS:
            result.status = amendment.newvalue
        elif amendment.field == tracker_pb2.FieldID.OWNER:
            if len(amendment.added_user_ids) == 0:
                result.owner = framework_constants.NO_USER_NAME
            else:
                result.owner = _get_user_email(services.user, mar.cnxn,
                                               amendment.added_user_ids[0])
        elif amendment.field == tracker_pb2.FieldID.LABELS:
            result.labels = amendment.newvalue.split()
        elif amendment.field == tracker_pb2.FieldID.CC:
            for user_id in amendment.added_user_ids:
                user_email = _get_user_email(services.user, mar.cnxn, user_id)
                result.cc.append(user_email)
            for user_id in amendment.removed_user_ids:
                user_email = _get_user_email(services.user, mar.cnxn, user_id)
                result.cc.append('-%s' % user_email)
        elif amendment.field == tracker_pb2.FieldID.BLOCKEDON:
            result.blockedOn = _append_project(amendment.newvalue,
                                               issue.project_name)
        elif amendment.field == tracker_pb2.FieldID.BLOCKING:
            result.blocking = _append_project(amendment.newvalue,
                                              issue.project_name)
        elif amendment.field == tracker_pb2.FieldID.MERGEDINTO:
            result.mergedInto = amendment.newvalue
        elif amendment.field == tracker_pb2.FieldID.COMPONENTS:
            result.components = amendment.newvalue.split()
        elif amendment.field == tracker_pb2.FieldID.CUSTOM:
            fv = api_pb2_v1.FieldValue()
            fv.fieldName = amendment.custom_field_name
            fv.fieldValue = tracker_bizobj.AmendmentString(
                amendment, users_by_id)
            result.fieldValues.append(fv)

    return result
Example #29
0
    def ListReferencedIssues(self, mc, request):
        """Return the specified issues in a response proto."""
        if not request.issue_refs:
            return issues_pb2.ListReferencedIssuesResponse()

        for issue_ref in request.issue_refs:
            if not issue_ref.project_name:
                raise exceptions.InputException(
                    'Param `project_name` required.')
            if not issue_ref.local_id:
                raise exceptions.InputException('Param `local_id` required.')

        default_project_name = request.issue_refs[0].project_name
        ref_tuples = [(ref.project_name, ref.local_id)
                      for ref in request.issue_refs]
        with work_env.WorkEnv(mc, self.services) as we:
            open_issues, closed_issues = we.ListReferencedIssues(
                ref_tuples, default_project_name)
            all_issues = open_issues + closed_issues
            all_project_ids = [issue.project_id for issue in all_issues]
            related_refs = we.GetRelatedIssueRefs(all_issues)
            configs = we.GetProjectConfigs(all_project_ids)

        with mc.profiler.Phase('making user views'):
            users_involved = tracker_bizobj.UsersInvolvedInIssues(all_issues)
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved)
            framework_views.RevealAllEmailsToMembers(mc.auth, None,
                                                     users_by_id)

        with mc.profiler.Phase('converting to response objects'):
            converted_open_issues = [
                converters.ConvertIssue(issue, users_by_id, related_refs,
                                        configs[issue.project_id])
                for issue in open_issues
            ]
            converted_closed_issues = [
                converters.ConvertIssue(issue, users_by_id, related_refs,
                                        configs[issue.project_id])
                for issue in closed_issues
            ]
            response = issues_pb2.ListReferencedIssuesResponse(
                open_refs=converted_open_issues,
                closed_refs=converted_closed_issues)

        return response
Example #30
0
    def GetIssue(self, mc, request):
        """Return the specified issue in a response proto."""
        issue_ref = request.issue_ref
        project, issue, config = self._GetProjectIssueAndConfig(
            mc, issue_ref, view_deleted=True, issue_required=False)

        # Code for getting where a moved issue was moved to.
        if issue is None:
            moved_to_ref = self.services.issue.GetCurrentLocationOfMovedIssue(
                mc.cnxn, project.project_id, issue_ref.local_id)
            moved_to_project_id, moved_to_id = moved_to_ref
            moved_to_project_name = None

            if moved_to_project_id is not None:
                with work_env.WorkEnv(mc, self.services) as we:
                    moved_to_project = we.GetProject(moved_to_project_id)
                    moved_to_project_name = moved_to_project.project_name
                return issues_pb2.IssueResponse(
                    moved_to_ref=converters.ConvertIssueRef((
                        moved_to_project_name, moved_to_id)))

            raise exceptions.NoSuchIssueException()

        if issue.deleted:
            return issues_pb2.IssueResponse(issue=issue_objects_pb2.Issue(
                is_deleted=True))

        with work_env.WorkEnv(mc, self.services) as we:
            related_refs = we.GetRelatedIssueRefs([issue])

        with mc.profiler.Phase('making user views'):
            users_involved_in_issue = tracker_bizobj.UsersInvolvedInIssues(
                [issue])
            users_by_id = framework_views.MakeAllUserViews(
                mc.cnxn, self.services.user, users_involved_in_issue)
            framework_views.RevealAllEmailsToMembers(mc.auth, project,
                                                     users_by_id)

        with mc.profiler.Phase('converting to response objects'):
            response = issues_pb2.IssueResponse()
            response.issue.CopyFrom(
                converters.ConvertIssue(issue, users_by_id, related_refs,
                                        config))

        return response