Example #1
0
 def testGetIntListParam_MultiValue(self):
     mr = monorailrequest.MonorailRequest()
     mr.ParseRequest(webapp2.Request.blank('servlet?ids=21,22,23'),
                     self.services, self.profiler)
     self.assertEquals(mr.GetIntListParam('ids'), [21, 22, 23])
     self.assertEquals(mr.GetIntListParam('ids', default_value=['test']),
                       [21, 22, 23])
Example #2
0
 def testIssueListURL_NotCustomized(self):
     mr = monorailrequest.MonorailRequest()
     mr.query = None
     mr.can = 2
     mr.project = self.project
     mr.config = self.config
     self.assertEqual('', mr._CalcDefaultQuery())
Example #3
0
 def testGetIntListParam_NoParam(self):
     mr = monorailrequest.MonorailRequest()
     mr.ParseRequest(webapp2.Request.blank('servlet'), self.services,
                     self.profiler)
     self.assertEquals(mr.GetIntListParam('ids'), None)
     self.assertEquals(mr.GetIntListParam('ids', default_value=['test']),
                       ['test'])
Example #4
0
 def testDefaultValuesNoUrl(self):
   """If request has no param, default param values should be used."""
   mr = monorailrequest.MonorailRequest(self.services)
   mr.ParseRequest(webapp2.Request.blank('servlet'), self.services)
   self.assertEqual(mr.GetParam('r', 3), 3)
   self.assertEqual(mr.GetIntParam('r', 3), 3)
   self.assertEqual(mr.GetPositiveIntParam('r', 3), 3)
   self.assertEqual(mr.GetIntListParam('r', [3, 4]), [3, 4])
Example #5
0
 def testIssueListURL_Customized_Member(self):
     mr = monorailrequest.MonorailRequest()
     mr.query = None
     mr.can = 2
     mr.project = self.project
     mr.config = self.config
     mr.config.member_default_query = 'owner:me'
     mr.auth = testing_helpers.Blank(effective_ids={111L})
     self.assertEqual('owner:me', mr._CalcDefaultQuery())
 def setUp(self):
   project = project_pb2.Project()
   project.owner_ids.append(111)
   project.committer_ids.append(222)
   project.contributor_ids.append(333)
   project.contributor_ids.append(888)
   user = user_pb2.User()
   user.is_site_admin = False
   self.mr = monorailrequest.MonorailRequest(None)
   self.mr.project = project
   self.mr.auth.user_pb = user
Example #7
0
    def MakeRequestAsUser(self, project_name, email):
        self.mox.StubOutWithMock(users, 'get_current_user')
        users.get_current_user().AndReturn(
            testing_helpers.Blank(email=lambda: email))
        self.mox.ReplayAll()

        request = webapp2.Request.blank('/p/' + project_name)
        mr = monorailrequest.MonorailRequest()
        prof = profiler.Profiler()
        with prof.Phase('parse user info'):
            mr.ParseRequest(request, self.services, prof)
        return mr
  def testAssertBasePermission(self):
    """Only permit site admins and users viewing themselves."""
    mr = monorailrequest.MonorailRequest()
    mr.viewed_user_auth.user_id = 111L
    mr.auth.user_id = 222L

    self.assertRaises(permissions.PermissionException,
                      self.servlet.AssertBasePermission, mr)

    mr.auth.user_id = 111L
    self.servlet.AssertBasePermission(mr)

    mr.auth.user_id = 222L
    mr.auth.user_pb.is_site_admin = True
    self.servlet.AssertBasePermission(mr)
Example #9
0
    def testAssertBasePermission(self):
        servlet = banned.Banned('request', 'response', services=self.services)

        mr = monorailrequest.MonorailRequest(self.services)
        mr.auth.user_id = 0  # Anon user cannot see banned page.
        with self.assertRaises(webapp2.HTTPException) as cm:
            servlet.AssertBasePermission(mr)
        self.assertEquals(404, cm.exception.code)

        mr.auth.user_id = 111  # User who is not banned cannot view banned page.
        with self.assertRaises(webapp2.HTTPException) as cm:
            servlet.AssertBasePermission(mr)
        self.assertEquals(404, cm.exception.code)

        # This should not throw exception.
        mr.auth.user_pb.banned = 'spammer'
        servlet.AssertBasePermission(mr)
Example #10
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
Example #11
0
 def testIssueListURL_NoProject(self):
     mr = monorailrequest.MonorailRequest()
     mr.query = None
     mr.can = 2
     self.assertEqual('', mr._CalcDefaultQuery())
Example #12
0
 def _MRWithMockRequest(self, path, headers=None, *mr_args, **mr_kwargs):
     request = webapp2.Request.blank(path, headers=headers)
     mr = monorailrequest.MonorailRequest(*mr_args, **mr_kwargs)
     mr.ParseRequest(request, self.services, self.profiler)
     return mr
Example #13
0
 def testGetIntListParam_Malformed(self):
     mr = monorailrequest.MonorailRequest()
     with self.assertRaises(monorailrequest.InputException):
         mr.ParseRequest(webapp2.Request.blank('servlet?ids=31,32,,'),
                         self.services, self.profiler)
Example #14
0
 def testGetIntListParam_BogusValue(self):
     mr = monorailrequest.MonorailRequest()
     with self.assertRaises(monorailrequest.InputException):
         mr.ParseRequest(webapp2.Request.blank('servlet?ids=not_an_int'),
                         self.services, self.profiler)
Example #15
0
  def _MakeApprovalEmailTasks(
      self, hostport, issue, project, approval_value, approval_name,
      comment, users_by_id, user_ids_from_fields, perms):
    """Formulate emails to be sent."""

    # TODO(jojwang): avoid need to make MonorailRequest and autolinker
    # for comment_view OR make make tracker_views._ParseTextRuns public
    # and only pass text_runs to email_data.
    mr = monorailrequest.MonorailRequest(self.services)
    mr.project_name = project.project_name
    mr.project = project
    mr.perms = perms
    autolinker = autolink.Autolink()

    approval_url = framework_helpers.IssueCommentURL(
        hostport, project, issue.local_id, seq_num=comment.sequence)

    comment_view = tracker_views.IssueCommentView(
        project.project_name, comment, users_by_id, autolinker, {}, mr, issue)
    domain_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, project.project_name, '/issues/')

    commenter_view = users_by_id[comment.user_id]
    email_data = {
        'domain_url': domain_url,
        'approval_url': approval_url,
        'comment': comment_view,
        'issue_local_id': issue.local_id,
        'summary': issue.summary,
        }
    subject = '%s Approval: %s (Issue %s)' % (
        approval_name, issue.summary, issue.local_id)
    email_body = self.email_template.GetResponse(email_data)
    body = notify_helpers._TruncateBody(email_body)

    recipient_ids = self._GetApprovalEmailRecipients(
        approval_value, comment, issue, user_ids_from_fields,
        omit_ids=[comment.user_id])
    direct, indirect = self.services.usergroup.ExpandAnyGroupEmailRecipients(
        mr.cnxn, recipient_ids)
    # group ids were found in recipient_ids.
    # Re-set recipient_ids to remove group_ids
    if indirect:
      recipient_ids = set(direct + indirect)
      users_by_id.update(framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, indirect))  # already contains direct

    # TODO(jojwang): monorail:3588, refine email contents based on direct
    # and indirect user_ids returned.

    email_tasks = []
    for rid in recipient_ids:
      # TODO(jojwang): monorail:3588, add reveal_addr based on
      # recipient member status
      from_addr = emailfmt.FormatFromAddr(
          project, commenter_view=commenter_view, can_reply_to=False)
      dest_email = users_by_id[rid].email
      email_tasks.append(
          dict(from_addr=from_addr, to=dest_email, subject=subject, body=body)
      )

    return email_tasks
Example #16
0
 def testIssueListURL_NoConfig(self):
   mr = monorailrequest.MonorailRequest(None)
   mr.query = None
   mr.can = 2
   mr.project = self.project
   self.assertEqual('', mr._CalcDefaultQuery())
Example #17
0
 def testIssueListURL_NotDefaultCan(self):
   mr = monorailrequest.MonorailRequest(None)
   mr.query = None
   mr.can = 1
   self.assertEqual('', mr._CalcDefaultQuery())
Example #18
0
 def testGetIntListParam_OneValue(self):
   mr = monorailrequest.MonorailRequest(self.services)
   mr.ParseRequest(webapp2.Request.blank('servlet?ids=11'), self.services)
   self.assertEqual(mr.GetIntListParam('ids'), [11])
   self.assertEqual(mr.GetIntListParam('ids', default_value=['test']),
                     [11])
Example #19
0
    def dispatch(self):
        """Do common stuff then dispatch the request to get() or put() methods."""
        handler_start_time = time.time()

        logging.info('\n\n\nRequest handler: %r', self)
        count0, count1, count2 = gc.get_count()
        logging.info('gc counts: %d %d %d', count0, count1, count2)
        GC_COUNT.add(count0, {'generation': 0})
        GC_COUNT.add(count1, {'generation': 1})
        GC_COUNT.add(count2, {'generation': 2})

        self.mr = monorailrequest.MonorailRequest(self.services)

        self.ratelimiter.CheckStart(self.request)
        self.response.headers.add('Strict-Transport-Security',
                                  'max-age=31536000; includeSubDomains')

        if 'X-Cloud-Trace-Context' in self.request.headers:
            self.mr.profiler.trace_context = (
                self.request.headers.get('X-Cloud-Trace-Context'))
        if trace_service is not None:
            self.mr.profiler.trace_service = trace_service

        if self.services.cache_manager:
            # TODO(jrobbins): don't do this step if invalidation_timestep was
            # passed via the request and matches our last timestep
            try:
                with self.mr.profiler.Phase('distributed invalidation'):
                    self.services.cache_manager.DoDistributedInvalidation(
                        self.mr.cnxn)

            except MySQLdb.OperationalError as e:
                logging.exception(e)
                page_data = {
                    'http_response_code': httplib.SERVICE_UNAVAILABLE,
                    'requested_url': self.request.url,
                }
                self.template = template_helpers.GetTemplate(
                    'templates/framework/database-maintenance.ezt',
                    eliminate_blank_lines=self._ELIMINATE_BLANK_LINES)
                self.template.WriteResponse(self.response,
                                            page_data,
                                            content_type='text/html')
                return

        try:
            with self.mr.profiler.Phase('parsing request and doing lookups'):
                self.mr.ParseRequest(self.request, self.services)

            self.response.headers['X-Frame-Options'] = 'SAMEORIGIN'
            webapp2.RequestHandler.dispatch(self)

        except exceptions.NoSuchUserException as e:
            logging.warning('Trapped NoSuchUserException %s', e)
            self.abort(404, 'user not found')

        except exceptions.NoSuchGroupException as e:
            logging.warning('Trapped NoSuchGroupException %s', e)
            self.abort(404, 'user group not found')

        except exceptions.InputException as e:
            logging.info('Rejecting invalid input: %r', e)
            self.response.status = httplib.BAD_REQUEST

        except exceptions.NoSuchProjectException as e:
            logging.info('Rejecting invalid request: %r', e)
            self.response.status = httplib.NOT_FOUND

        except xsrf.TokenIncorrect as e:
            logging.info('Bad XSRF token: %r', e.message)
            self.response.status = httplib.BAD_REQUEST

        except permissions.BannedUserException as e:
            logging.warning('The user has been banned')
            url = framework_helpers.FormatAbsoluteURL(self.mr,
                                                      urls.BANNED,
                                                      include_project=False,
                                                      copy_params=False)
            self.redirect(url, abort=True)

        except ratelimiter.RateLimitExceeded as e:
            logging.info('RateLimitExceeded Exception %s', e)
            self.response.status = httplib.BAD_REQUEST
            self.response.body = 'Slow your roll.'

        finally:
            self.mr.CleanUp()
            self.ratelimiter.CheckEnd(self.request, time.time(),
                                      handler_start_time)

        total_processing_time = time.time() - handler_start_time
        logging.warn('Processed request in %d ms',
                     int(total_processing_time * 1000))

        end_count0, end_count1, end_count2 = gc.get_count()
        logging.info('gc counts: %d %d %d', end_count0, end_count1, end_count2)
        if (end_count0 < count0) or (end_count1 < count1) or (end_count2 <
                                                              count2):
            GC_EVENT_REQUEST.increment()

        if settings.enable_profiler_logging:
            self.mr.profiler.LogStats()

        if (self.mr.profiler.trace_context is not None
                and random.random() < settings.trace_fraction):
            self.mr.profiler.ReportTrace()
Example #20
0
    def dispatch(self):
        """Do common stuff then dispatch the request to get() or put() methods."""
        handler_start_time = time.time()

        logging.info('\n\n\nRequest handler: %r', self)

        self.mr = monorailrequest.MonorailRequest()

        self.ratelimiter.CheckStart(self.request)
        self.response.headers.add('Strict-Transport-Security',
                                  'max-age=31536000; includeSubDomains')

        if self.services.cache_manager:
            # TODO(jrobbins): don't do this step if invalidation_timestep was
            # passed via the request and matches our last timestep
            try:
                with self.profiler.Phase('distributed invalidation'):
                    self.services.cache_manager.DoDistributedInvalidation(
                        self.mr.cnxn)

            except MySQLdb.OperationalError as e:
                logging.exception(e)
                page_data = {
                    'http_response_code': httplib.SERVICE_UNAVAILABLE,
                    'requested_url': self.request.url,
                }
                self.template = template_helpers.GetTemplate(
                    'templates/framework/database-maintenance.ezt',
                    eliminate_blank_lines=self._ELIMINATE_BLANK_LINES)
                self.template.WriteResponse(self.response,
                                            page_data,
                                            content_type='text/html')
                return

        try:
            with self.profiler.Phase('parsing request and doing lookups'):
                self.mr.ParseRequest(self.request, self.services,
                                     self.profiler)

            self.response.headers['X-Frame-Options'] = 'SAMEORIGIN'
            webapp2.RequestHandler.dispatch(self)

        except user_svc.NoSuchUserException as e:
            logging.warning('Trapped NoSuchUserException %s', e)
            self.abort(404, 'user not found')

        except usergroup_svc.NoSuchGroupException as e:
            logging.warning('Trapped NoSuchGroupException %s', e)
            self.abort(404, 'user group not found')

        except monorailrequest.InputException as e:
            logging.info('Rejecting invalid input: %r', e)
            self.response.status = httplib.BAD_REQUEST

        except project_svc.NoSuchProjectException as e:
            logging.info('Rejecting invalid request: %r', e)
            self.response.status = httplib.BAD_REQUEST

        except xsrf.TokenIncorrect as e:
            logging.info('Bad XSRF token: %r', e.message)
            self.response.status = httplib.BAD_REQUEST

        except AlreadySentResponseException:
            # If servlet already sent response, then do nothing more.  E.g.,
            # when serving attachment content, we do not use templates.
            pass

        except permissions.BannedUserException as e:
            logging.warning('The user has been banned')
            url = framework_helpers.FormatAbsoluteURL(self.mr,
                                                      urls.BANNED,
                                                      include_project=False,
                                                      copy_params=False)
            self.redirect(url, abort=True)

        except actionlimit.ExcessiveActivityException:
            logging.info('Excessive Activity Exception %r',
                         self.mr.auth.user_id)
            url = framework_helpers.FormatAbsoluteURL(self.mr,
                                                      urls.EXCESSIVE_ACTIVITY,
                                                      include_project=False,
                                                      copy_params=False)
            self.redirect(url, abort=True)

        except ratelimiter.RateLimitExceeded as e:
            logging.info('RateLimitExceeded Exception %s', e)
            self.response.status = httplib.BAD_REQUEST
            self.response.body = 'Slow your roll.'

        finally:
            self.mr.CleanUp()
            self.ratelimiter.CheckEnd(self.request, time.time(),
                                      handler_start_time)

        total_processing_time = time.time() - handler_start_time
        logging.warn('Processed request in %d ms',
                     int(total_processing_time * 1000))
        if settings.enable_profiler_logging:
            self.profiler.LogStats()