def testComputeGroupReasonList_NotifyAll(self):
    """Project is configured to always notify [email protected]."""
    self.project.issue_notify_address = '*****@*****.**'
    actual = notify_reasons.ComputeGroupReasonList(
        'cnxn', self.services, self.project, self.issue, self.config,
        self.users_by_id, [], True)
    self.CheckGroupReasonList(
        actual,
        owner_apl=[notify_reasons.AddrPerm(
            False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)],
        all_notifications_apl=[notify_reasons.AddrPerm(
            False, '*****@*****.**', None, REPLY_NOT_ALLOWED)])

    # We don't use the notify-all address when the issue is not public.
    actual = notify_reasons.ComputeGroupReasonList(
        'cnxn', self.services, self.project, self.issue, self.config,
        self.users_by_id, [], False)
    self.CheckGroupReasonList(
        actual,
        owner_apl=[notify_reasons.AddrPerm(
            False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)])

    # Now with the notify-all address disabled.
    actual = notify_reasons.ComputeGroupReasonList(
        'cnxn', self.services, self.project, self.issue, self.config,
        self.users_by_id, [], True, include_notify_all=False)
    self.CheckGroupReasonList(
        actual,
        owner_apl=[notify_reasons.AddrPerm(
            False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)])
  def testComputeGroupReasonList_Subscribers(self):
    """Bob subscribed."""
    sq = tracker_bizobj.MakeSavedQuery(
          1, 'freds issues', 1, 'owner:[email protected]',
          subscription_mode='immediate', executes_in_project_ids=[789])
    self.services.features.UpdateUserSavedQueries(
        'cnxn', self.bob.user_id, [sq])
    actual = notify_reasons.ComputeGroupReasonList(
        'cnxn', self.services, self.project, self.issue, self.config,
        self.users_by_id, [], True)
    self.CheckGroupReasonList(
        actual,
        owner_apl=[notify_reasons.AddrPerm(
            False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)],
        subscriber_apl=[notify_reasons.AddrPerm(
            False, self.bob.email, self.bob, REPLY_NOT_ALLOWED)])

    # Now with subscriber notifications disabled.
    actual = notify_reasons.ComputeGroupReasonList(
        'cnxn', self.services, self.project, self.issue, self.config,
        self.users_by_id, [], True, include_subscribers=False)
    self.CheckGroupReasonList(
        actual,
        owner_apl=[notify_reasons.AddrPerm(
            False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)])
Exemplo n.º 3
0
    def _MakeEmailTasks(self, cnxn, issue, project, config, comment, hostport,
                        users_by_id, pings):
        """Return a list of dicts for tasks to notify people."""
        detail_url = framework_helpers.IssueCommentURL(
            hostport, project, issue.local_id, seq_num=comment.sequence)
        fields = sorted((field_def for (field_def, _date_value) in pings),
                        key=lambda fd: fd.field_name)
        email_data = {
            'issue': tracker_views.IssueView(issue, users_by_id, config),
            'summary': issue.summary,
            'ping_comment_content': comment.content,
            'detail_url': detail_url,
            'fields': fields,
        }

        # Generate two versions of email body: members version has all
        # full email addresses exposed.
        body_for_non_members = self.email_template.GetResponse(email_data)
        framework_views.RevealAllEmails(users_by_id)
        body_for_members = self.email_template.GetResponse(email_data)
        logging.info('body for non-members is:\n%r' % body_for_non_members)
        logging.info('body for members is:\n%r' % body_for_members)

        contributor_could_view = permissions.CanViewIssue(
            set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, project,
            issue)
        # Note: We never notify the reporter of any issue just because they
        # reported it, only if they star it.
        # TODO(jrobbins): add a user preference for notifying starrers.
        starrer_ids = []

        # TODO(jrobbins): consider IsNoisy() when we support notifying starrers.
        group_reason_list = notify_reasons.ComputeGroupReasonList(
            cnxn,
            self.services,
            project,
            issue,
            config,
            users_by_id, [],
            contributor_could_view,
            starrer_ids=starrer_ids,
            commenter_in_project=True)

        commenter_view = users_by_id[comment.user_id]
        email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
            group_reason_list,
            issue,
            body_for_non_members,
            body_for_members,
            project,
            hostport,
            commenter_view,
            detail_url,
            seq_num=comment.sequence,
            subject_prefix='Follow up on issue ',
            compact_subject_prefix='Follow up ')

        return email_tasks
Exemplo n.º 4
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 testComputeGroupReasonList_OwnerAndCC(self):
   """Fred owns the issue, Alice is CC'd."""
   self.issue.cc_ids = [self.alice.user_id]
   actual = notify_reasons.ComputeGroupReasonList(
       'cnxn', self.services, self.project, self.issue, self.config,
       self.users_by_id, [], True)
   self.CheckGroupReasonList(
       actual,
       owner_apl=[notify_reasons.AddrPerm(
           False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)],
       ccd_apl=[notify_reasons.AddrPerm(
           False, self.alice.email, self.alice, REPLY_NOT_ALLOWED)])
 def testComputeGroupReasonList_Starrers(self):
   """Bob and Alice starred it, but Alice opts out of notifications."""
   self.alice.notify_starred_issue_change = False
   actual = notify_reasons.ComputeGroupReasonList(
       'cnxn', self.services, self.project, self.issue, self.config,
       self.users_by_id, [], True,
       starrer_ids=[self.alice.user_id, self.bob.user_id])
   self.CheckGroupReasonList(
       actual,
       owner_apl=[notify_reasons.AddrPerm(
           False, self.fred.email, self.fred, REPLY_NOT_ALLOWED)],
       starrer_apl=[notify_reasons.AddrPerm(
           False, self.bob.email, self.bob, REPLY_NOT_ALLOWED)])
Exemplo n.º 7
0
  def _MakeEmailTasks(
      self, cnxn, project, issue, config, old_owner_id,
      users_by_id, all_comments, comment, starrer_ids,
      contributor_could_view, hostport, omit_ids, perms):
    """Formulate emails to be sent."""
    detail_url = framework_helpers.IssueCommentURL(
        hostport, project, issue.local_id, seq_num=comment.sequence)

    # TODO(jrobbins): avoid the need to make a MonorailRequest object.
    mr = monorailrequest.MonorailRequest(self.services)
    mr.project_name = project.project_name
    mr.project = project
    mr.perms = perms

    # We do not autolink in the emails, so just use an empty
    # registry of autolink rules.
    # TODO(jrobbins): offer users an HTML email option w/ autolinks.
    autolinker = autolink.Autolink()
    was_created = ezt.boolean(comment.sequence == 0)

    email_data = {
        # Pass open_related and closed_related into this method and to
        # the issue view so that we can show it on new issue email.
        'issue': tracker_views.IssueView(issue, users_by_id, config),
        'summary': issue.summary,
        'comment': tracker_views.IssueCommentView(
            project.project_name, comment, users_by_id,
            autolinker, {}, mr, issue),
        'comment_text': comment.content,
        'detail_url': detail_url,
        'was_created': was_created,
        }

    # Generate three versions of email body: link-only is just the link,
    # non-members see some obscured email addresses, and members version has
    # all full email addresses exposed.
    body_link_only = self.link_only_email_template.GetResponse(
      {'detail_url': detail_url, 'was_created': was_created})
    body_for_non_members = self.email_template.GetResponse(email_data)
    framework_views.RevealAllEmails(users_by_id)
    email_data['comment'] = tracker_views.IssueCommentView(
        project.project_name, comment, users_by_id,
        autolinker, {}, mr, issue)
    body_for_members = self.email_template.GetResponse(email_data)

    logging.info('link-only body is:\n%r' % body_link_only)
    logging.info('body for non-members is:\n%r' % body_for_non_members)
    logging.info('body for members is:\n%r' % body_for_members)

    commenter_email = users_by_id[comment.user_id].email
    omit_addrs = set([commenter_email] +
                     [users_by_id[omit_id].email for omit_id in omit_ids])

    auth = authdata.AuthData.FromUserID(
        cnxn, comment.user_id, self.services)
    commenter_in_project = framework_bizobj.UserIsInProject(
        project, auth.effective_ids)
    noisy = tracker_helpers.IsNoisy(len(all_comments) - 1, len(starrer_ids))

    # Give each user a bullet-list of all the reasons that apply for that user.
    group_reason_list = notify_reasons.ComputeGroupReasonList(
        cnxn, self.services, project, issue, config, users_by_id,
        omit_addrs, contributor_could_view, noisy=noisy,
        starrer_ids=starrer_ids, old_owner_id=old_owner_id,
        commenter_in_project=commenter_in_project)

    commenter_view = users_by_id[comment.user_id]
    detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, issue.project_name, urls.ISSUE_DETAIL,
        id=issue.local_id)
    email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
        group_reason_list, issue, body_link_only, body_for_non_members,
        body_for_members, project, hostport, commenter_view, detail_url,
        seq_num=comment.sequence)

    return email_tasks
Exemplo n.º 8
0
    def _MakeEmailTasks(self, cnxn, issue, project, config, comment,
                        starrer_ids, hostport, users_by_id, pings):
        """Return a list of dicts for tasks to notify people."""
        detail_url = framework_helpers.IssueCommentURL(
            hostport, project, issue.local_id, seq_num=comment.sequence)
        fields = sorted((field_def for (field_def, _date_value) in pings),
                        key=lambda fd: fd.field_name)
        email_data = {
            'issue': tracker_views.IssueView(issue, users_by_id, config),
            'summary': issue.summary,
            'ping_comment_content': comment.content,
            'detail_url': detail_url,
            'fields': fields,
        }

        # Generate three versions of email body with progressively more info.
        body_link_only = self.link_only_email_template.GetResponse({
            'detail_url':
            detail_url,
            'was_created':
            ezt.boolean(False)
        })
        body_for_non_members = self.email_template.GetResponse(email_data)
        framework_views.RevealAllEmails(users_by_id)
        body_for_members = self.email_template.GetResponse(email_data)
        logging.info('body for non-members is:\n%r' % body_for_non_members)
        logging.info('body for members is:\n%r' % body_for_members)

        contributor_could_view = permissions.CanViewIssue(
            set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, project,
            issue)

        group_reason_list = notify_reasons.ComputeGroupReasonList(
            cnxn,
            self.services,
            project,
            issue,
            config,
            users_by_id, [],
            contributor_could_view,
            starrer_ids=starrer_ids,
            commenter_in_project=True,
            include_subscribers=False,
            include_notify_all=False,
            starrer_pref_check_function=lambda u: u.notify_starred_ping)

        commenter_view = users_by_id[comment.user_id]
        email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
            group_reason_list,
            issue,
            body_link_only,
            body_for_non_members,
            body_for_members,
            project,
            hostport,
            commenter_view,
            detail_url,
            seq_num=comment.sequence,
            subject_prefix='Follow up on issue ',
            compact_subject_prefix='Follow up ')

        return email_tasks