Пример #1
0
  def testGatherPageData_DefaultOwnerAvailability(self):
    user = self.services.user.TestAddUser('user@invalid', 100)
    mr = testing_helpers.MakeMonorailRequest(
        path='/p/proj/issues/entry', services=self.services)
    mr.auth.user_view = framework_views.MakeUserView(
        'cnxn', self.services.user, 100)
    mr.template_name = 'rutabaga'

    self.mox.StubOutWithMock(self.services.user, 'GetUser')
    self.services.user.GetUser(
        mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user)
    self.mox.ReplayAll()

    page_data = self.servlet.GatherPageData(mr)
    self.mox.VerifyAll()
    self.assertEqual(page_data['initial_owner'], 'user@invalid')
    self.assertEqual(page_data['owner_avail_state'], 'never')
    self.assertEqual(
        page_data['owner_avail_message_short'],
        'User never visited')

    user.last_visit_timestamp = int(time.time())
    mr.auth.user_view = framework_views.MakeUserView(
        'cnxn', self.services.user, 100)
    page_data = self.servlet.GatherPageData(mr)
    self.mox.VerifyAll()
    self.assertEqual(page_data['initial_owner'], 'user@invalid')
    self.assertEqual(page_data['owner_avail_state'], None)
    self.assertEqual(page_data['owner_avail_message_short'], '')
Пример #2
0
  def testGatherPageData_Approvals(self):
    user = self.services.user.TestAddUser('user@invalid', 100)
    mr = testing_helpers.MakeMonorailRequest(
        path='/p/proj/issues/entry', services=self.services)
    mr.auth.user_view = framework_views.MakeUserView(
        'cnxn', self.services.user, 100)
    mr.template_name = 'rutabaga'

    self.mox.StubOutWithMock(self.services.user, 'GetUser')
    self.services.user.GetUser(
        mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user)
    self.mox.ReplayAll()
    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    config.field_defs = [
    tracker_bizobj.MakeFieldDef(
        24, mr.project_id, 'UXReview',
        tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False,
        False, None, None, '', False, '', '',
        tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)]
    self.services.config.StoreConfig(mr.cnxn, config)
    template = tracker_pb2.TemplateDef()
    template.phases = [tracker_pb2.Phase(
        phase_id=1, rank=4, name='Stable')]
    template.approval_values = [tracker_pb2.ApprovalValue(
        approval_id=24, phase_id=1,
        status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW)]
    self.services.template.GetTemplateByName.return_value = template

    page_data = self.servlet.GatherPageData(mr)
    self.mox.VerifyAll()
    self.assertEqual(page_data['approvals'][0].field_name, 'UXReview')
    self.assertEqual(page_data['initial_phases'][0],
                          tracker_pb2.Phase(phase_id=1, name='Stable', rank=4))
    self.assertEqual(page_data['prechecked_approvals'], ['24_phase_0'])
    self.assertEqual(page_data['required_approval_ids'], [24])

    # phase fields row shown when config contains phase fields.
    config.field_defs.append(tracker_bizobj.MakeFieldDef(
        26, mr.project_id, 'GateTarget',
        tracker_pb2.FieldTypes.INT_TYPE, None, '', False, False, False,
        None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER,
        'no_action', 'doc', False, is_phase_field=True))
    self.services.config.StoreConfig(mr.cnxn, config)
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(page_data['issue_phase_names'], ['stable'])

    # approval subfields in config hidden when chosen template does not contain
    # its parent approval
    template = tracker_pb2.TemplateDef()
    self.services.template.GetTemplateByName.return_value = template
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(page_data['approvals'], [])
    # phase fields row hidden when template has no phases
    self.assertEqual(page_data['issue_phase_names'], [])
Пример #3
0
 def testProcessFormData_ok(self):
     self.servlet.services.user.TestAddUser('owner', 222)
     self.servlet.services.user.TestAddUser('*****@*****.**', 111)
     mr = testing_helpers.MakeMonorailRequest(
         path='/u/[email protected]/banSpammer.do',
         perms=permissions.ADMIN_PERMISSIONSET)
     mr.viewed_user_auth.user_view = framework_views.MakeUserView(
         mr.cnxn, self.servlet.services.user, 111)
     self.servlet.ProcessFormData(mr, {})
     tasks = self.taskqueue_stub.get_filtered_tasks(
         url=urls.BAN_SPAMMER_TASK + '.do')
     self.assertEqual(1, len(tasks))
Пример #4
0
 def testProcessFormData_noPermission(self):
     self.servlet.services.user.TestAddUser('member', 222)
     self.servlet.services.user.TestAddUser('*****@*****.**', 111)
     mr = testing_helpers.MakeMonorailRequest(
         path='/u/[email protected]/banSpammer.do',
         perms=permissions.GetPermissions(None, {}, None))
     mr.viewed_user_auth.user_view = framework_views.MakeUserView(
         mr.cnxn, self.servlet.services.user, 111)
     mr.auth.user_id = 222
     self.assertRaises(permissions.PermissionException,
                       self.servlet.AssertBasePermission, mr)
     try:
         self.servlet.ProcessFormData(mr, {})
     except permissions.PermissionException:
         pass
     tasks = self.taskqueue_stub.get_filtered_tasks(
         url=urls.BAN_SPAMMER_TASK + '.do')
     self.assertEqual(0, len(tasks))
Пример #5
0
    def testGatherPageData(self):
        user = self.services.user.TestAddUser('user@invalid', 100)
        mr = testing_helpers.MakeMonorailRequest(path='/p/proj/issues/entry',
                                                 services=self.services)
        mr.auth.user_view = framework_views.MakeUserView(
            'cnxn', self.services.user, 100)

        self.mox.StubOutWithMock(self.services.user, 'GetUser')
        self.services.user.GetUser(
            mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user)
        self.mox.ReplayAll()

        page_data = self.servlet.GatherPageData(mr)
        self.mox.VerifyAll()
        self.assertEqual(page_data['initial_owner'], 'user@invalid')
        self.assertEqual(page_data['initial_status'], 'New')
        self.assertTrue(page_data['clear_summary_on_click'])
        self.assertTrue(page_data['must_edit_summary'])
Пример #6
0
  def testGatherPageData(self):
    user = self.services.user.TestAddUser('user@invalid', 100)
    mr = testing_helpers.MakeMonorailRequest(
        path='/p/proj/issues/entry', services=self.services)
    mr.auth.user_view = framework_views.MakeUserView(
        'cnxn', self.services.user, 100)
    mr.template_name = 'rutabaga'

    self.mox.StubOutWithMock(self.services.user, 'GetUser')
    self.services.user.GetUser(
        mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user)
    self.mox.ReplayAll()
    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    config.field_defs = [
        tracker_bizobj.MakeFieldDef(
            24, mr.project_id, 'NotEnum',
            tracker_pb2.FieldTypes.STR_TYPE, None, '', False, False,
            False, None, None, '', False, '', '',
            tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False),
        tracker_bizobj.MakeFieldDef(
            24, mr.project_id, 'Choices',
            tracker_pb2.FieldTypes.ENUM_TYPE, None, '', False, False,
            False, None, None, '', False, '', '',
            tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)]
    self.services.config.StoreConfig(mr.cnxn, config)
    template = tracker_pb2.TemplateDef(
        labels=['NotEnum-Not-Masked', 'Choices-Masked'])
    self.services.template.GetTemplateByName.return_value = template

    page_data = self.servlet.GatherPageData(mr)
    self.mox.VerifyAll()
    self.assertEqual(page_data['initial_owner'], 'user@invalid')
    self.assertEqual(page_data['initial_status'], 'New')
    self.assertTrue(page_data['clear_summary_on_click'])
    self.assertTrue(page_data['must_edit_summary'])
    self.assertEqual(page_data['labels'], ['NotEnum-Not-Masked'])
Пример #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.
    """
        with mr.profiler.Phase('getting config'):
            config = self.services.config.GetProjectConfig(
                mr.cnxn, mr.project_id)

        # In addition to checking perms, we adjust some default field values for
        # project members.
        is_member = framework_bizobj.UserIsInProject(mr.project,
                                                     mr.auth.effective_ids)
        page_perms = self.MakePagePerms(
            mr, None, permissions.CREATE_ISSUE, permissions.SET_STAR,
            permissions.EDIT_ISSUE, permissions.EDIT_ISSUE_SUMMARY,
            permissions.EDIT_ISSUE_STATUS, permissions.EDIT_ISSUE_OWNER,
            permissions.EDIT_ISSUE_CC)

        with work_env.WorkEnv(mr, self.services) as we:
            userprefs = we.GetUserPrefs(mr.auth.user_id)
            code_font = any(
                pref for pref in userprefs.prefs
                if pref.name == 'code_font' and pref.value == 'true')

        template = self._GetTemplate(mr.cnxn, config, mr.template_name,
                                     is_member)

        if template.summary:
            initial_summary = template.summary
            initial_summary_must_be_edited = template.summary_must_be_edited
        else:
            initial_summary = PLACEHOLDER_SUMMARY
            initial_summary_must_be_edited = True

        if template.status:
            initial_status = template.status
        elif is_member:
            initial_status = 'Accepted'
        else:
            initial_status = 'New'  # not offering meta, only used in hidden field.

        component_paths = []
        for component_id in template.component_ids:
            component_paths.append(
                tracker_bizobj.FindComponentDefByID(component_id, config).path)
        initial_components = ', '.join(component_paths)

        if template.owner_id:
            initial_owner = framework_views.MakeUserView(
                mr.cnxn, self.services.user, template.owner_id)
        elif template.owner_defaults_to_member and page_perms.EditIssue:
            initial_owner = mr.auth.user_view
        else:
            initial_owner = None

        if initial_owner:
            initial_owner_name = initial_owner.email
            owner_avail_state = initial_owner.avail_state
            owner_avail_message_short = initial_owner.avail_message_short
        else:
            initial_owner_name = ''
            owner_avail_state = None
            owner_avail_message_short = None

        # Check whether to allow attachments from the entry page
        allow_attachments = tracker_helpers.IsUnderSoftAttachmentQuota(
            mr.project)

        config_view = tracker_views.ConfigView(mr, self.services, config,
                                               template)
        # If the user followed a link that specified the template name, make sure
        # that it is also in the menu as the current choice.
        # TODO(jeffcarp): Unit test this.
        config_view.template_view.can_view = ezt.boolean(True)

        # TODO(jeffcarp): Unit test this.
        offer_templates = len(config_view.template_names) > 1
        restrict_to_known = config.restrict_to_known
        enum_field_name_set = {
            fd.field_name.lower()
            for fd in config.field_defs
            if fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
            and not fd.is_deleted
        }  # TODO(jrobbins): restrictions
        link_or_template_labels = mr.GetListParam('labels', template.labels)
        labels = [
            lab for lab in link_or_template_labels if
            not tracker_bizobj.LabelIsMaskedByField(lab, enum_field_name_set)
        ]

        # Corp-mode users automatically add R-V-G.
        with work_env.WorkEnv(mr, self.services) as we:
            userprefs = we.GetUserPrefs(mr.auth.user_id)
            corp_mode = any(
                up.name == 'restrict_new_issues' and up.value == 'true'
                for up in userprefs.prefs)
            if corp_mode:
                if not any(lab.lower().startswith('restrict-view-')
                           for lab in labels):
                    labels.append(CORP_RESTRICTION_LABEL)

        field_user_views = tracker_views.MakeFieldUserViews(
            mr.cnxn, template, self.services.user)
        approval_ids = [av.approval_id for av in template.approval_values]
        field_views = tracker_views.MakeAllFieldValueViews(
            config,
            link_or_template_labels, [],
            template.field_values,
            field_user_views,
            parent_approval_ids=approval_ids,
            phases=template.phases)
        # TODO(jojwang): monorail:6305, remove this hack when Edit perms for field
        # values are implemented.
        field_views = [
            view for view in field_views
            if view.field_name.lower() not in RESTRICTED_FLT_FIELDS
        ]

        # TODO(jrobbins): remove "or []" after next release.
        (prechecked_approvals, required_approval_ids,
         phases) = issue_tmpl_helpers.GatherApprovalsPageData(
             template.approval_values or [], template.phases, config)
        approvals = [
            view for view in field_views if view.field_id in approval_ids
        ]

        page_data = {
            'issue_tab_mode':
            'issueEntry',
            'initial_summary':
            initial_summary,
            'template_summary':
            initial_summary,
            'clear_summary_on_click':
            ezt.boolean(initial_summary_must_be_edited
                        and 'initial_summary' not in mr.form_overrides),
            'must_edit_summary':
            ezt.boolean(initial_summary_must_be_edited),
            'initial_description':
            template.content,
            'template_name':
            template.name,
            'component_required':
            ezt.boolean(template.component_required),
            'initial_status':
            initial_status,
            'initial_owner':
            initial_owner_name,
            'owner_avail_state':
            owner_avail_state,
            'owner_avail_message_short':
            owner_avail_message_short,
            'initial_components':
            initial_components,
            'initial_cc':
            '',
            'initial_blocked_on':
            '',
            'initial_blocking':
            '',
            'initial_hotlists':
            '',
            'labels':
            labels,
            'fields':
            field_views,
            'any_errors':
            ezt.boolean(mr.errors.AnyErrors()),
            'page_perms':
            page_perms,
            'allow_attachments':
            ezt.boolean(allow_attachments),
            'max_attach_size':
            template_helpers.BytesKbOrMb(
                framework_constants.MAX_POST_BODY_SIZE),
            'offer_templates':
            ezt.boolean(offer_templates),
            'config':
            config_view,
            'restrict_to_known':
            ezt.boolean(restrict_to_known),
            'is_member':
            ezt.boolean(is_member),
            'code_font':
            ezt.boolean(code_font),
            # The following are necessary for displaying phases that come with
            # this template. These are read-only.
            'allow_edit':
            ezt.boolean(False),
            'initial_phases':
            phases,
            'approvals':
            approvals,
            'prechecked_approvals':
            prechecked_approvals,
            'required_approval_ids':
            required_approval_ids,
            # See monorail:4692 and the use of PHASES_WITH_MILESTONES
            # in elements/flt/mr-launch-overview/mr-phase.js
            'issue_phase_names':
            list({
                phase.name.lower()
                for phase in phases if phase.name in PHASES_WITH_MILESTONES
            }),
        }

        return page_data
Пример #8
0
    def __init__(self, mr, template, user_service, config):
        super(IssueTemplateView, self).__init__(template)

        self.ownername = ''
        try:
            self.owner_view = framework_views.MakeUserView(
                mr.cnxn, user_service, template.owner_id)
        except exceptions.NoSuchUserException:
            self.owner_view = None
        if self.owner_view:
            self.ownername = self.owner_view.email

        self.admin_views = list(
            framework_views.MakeAllUserViews(mr.cnxn, user_service,
                                             template.admin_ids).values())
        self.admin_names = ', '.join(
            sorted([admin_view.email for admin_view in self.admin_views]))

        self.summary_must_be_edited = ezt.boolean(
            template.summary_must_be_edited)
        self.members_only = ezt.boolean(template.members_only)
        self.owner_defaults_to_member = ezt.boolean(
            template.owner_defaults_to_member)
        self.component_required = ezt.boolean(template.component_required)

        component_paths = []
        for component_id in template.component_ids:
            component_paths.append(
                tracker_bizobj.FindComponentDefByID(component_id, config).path)
        self.components = ', '.join(component_paths)

        self.can_view = ezt.boolean(
            permissions.CanViewTemplate(mr.auth.effective_ids, mr.perms,
                                        mr.project, template))
        self.can_edit = ezt.boolean(
            permissions.CanEditTemplate(mr.auth.effective_ids, mr.perms,
                                        mr.project, template))

        field_name_set = {
            fd.field_name.lower()
            for fd in config.field_defs
            if fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
            and not fd.is_deleted
        }  # TODO(jrobbins): restrictions
        non_masked_labels = [
            lab for lab in template.labels
            if not tracker_bizobj.LabelIsMaskedByField(lab, field_name_set)
        ]

        for i, label in enumerate(non_masked_labels):
            setattr(self, 'label%d' % i, label)
        for i in range(len(non_masked_labels), framework_constants.MAX_LABELS):
            setattr(self, 'label%d' % i, '')

        field_user_views = MakeFieldUserViews(mr.cnxn, template, user_service)

        self.field_values = []
        for fv in template.field_values:
            self.field_values.append(
                template_helpers.EZTItem(field_id=fv.field_id,
                                         val=tracker_bizobj.GetFieldValue(
                                             fv, field_user_views),
                                         idx=len(self.field_values)))

        self.complete_field_values = MakeAllFieldValueViews(
            config, template.labels, [], template.field_values,
            field_user_views)

        # Templates only display and edit the first value of multi-valued fields, so
        # expose a single value, if any.
        # TODO(jrobbins): Fully support multi-valued fields in templates.
        for idx, field_value_view in enumerate(self.complete_field_values):
            field_value_view.idx = idx
            if field_value_view.values:
                field_value_view.val = field_value_view.values[0].val
            else:
                field_value_view.val = None
Пример #9
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.
    """
    with self.profiler.Phase('getting config'):
      config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    # In addition to checking perms, we adjust some default field values for
    # project members.
    is_member = framework_bizobj.UserIsInProject(
        mr.project, mr.auth.effective_ids)
    page_perms = self.MakePagePerms(
        mr, None,
        permissions.CREATE_ISSUE,
        permissions.SET_STAR,
        permissions.EDIT_ISSUE,
        permissions.EDIT_ISSUE_SUMMARY,
        permissions.EDIT_ISSUE_STATUS,
        permissions.EDIT_ISSUE_OWNER,
        permissions.EDIT_ISSUE_CC)

    wkp = _SelectTemplate(mr.template_name, config, is_member)

    if wkp.summary:
      initial_summary = wkp.summary
      initial_summary_must_be_edited = wkp.summary_must_be_edited
    else:
      initial_summary = PLACEHOLDER_SUMMARY
      initial_summary_must_be_edited = True

    if wkp.status:
      initial_status = wkp.status
    elif is_member:
      initial_status = 'Accepted'
    else:
      initial_status = 'New'  # not offering meta, only used in hidden field.

    component_paths = []
    for component_id in wkp.component_ids:
      component_paths.append(
          tracker_bizobj.FindComponentDefByID(component_id, config).path)
    initial_components = ', '.join(component_paths)

    if wkp.owner_id:
      initial_owner = framework_views.MakeUserView(
          mr.cnxn, self.services.user, wkp.owner_id)
    elif wkp.owner_defaults_to_member and page_perms.EditIssue:
      initial_owner = mr.auth.user_view
    else:
      initial_owner = None

    if initial_owner:
      initial_owner_name = initial_owner.email
      owner_avail_state = initial_owner.avail_state
      owner_avail_message_short = initial_owner.avail_message_short
    else:
      initial_owner_name = ''
      owner_avail_state = None
      owner_avail_message_short = None

    # Check whether to allow attachments from the entry page
    allow_attachments = tracker_helpers.IsUnderSoftAttachmentQuota(mr.project)

    config_view = tracker_views.ConfigView(mr, self.services, config)
    # If the user followed a link that specified the template name, make sure
    # that it is also in the menu as the current choice.
    for template_view in config_view.templates:
      if template_view.name == mr.template_name:
        template_view.can_view = ezt.boolean(True)

    offer_templates = len(list(
        tmpl for tmpl in config_view.templates if tmpl.can_view)) > 1
    restrict_to_known = config.restrict_to_known
    field_name_set = {fd.field_name.lower() for fd in config.field_defs
                      if not fd.is_deleted}  # TODO(jrobbins): restrictions
    link_or_template_labels = mr.GetListParam('labels', wkp.labels)
    labels = [lab for lab in link_or_template_labels
              if not tracker_bizobj.LabelIsMaskedByField(lab, field_name_set)]

    field_user_views = tracker_views.MakeFieldUserViews(
        mr.cnxn, wkp, self.services.user)
    field_views = [
        tracker_views.MakeFieldValueView(
            fd, config, link_or_template_labels, [], wkp.field_values,
            field_user_views)
        # TODO(jrobbins): field-level view restrictions, display options
        for fd in config.field_defs
        if not fd.is_deleted]

    page_data = {
        'issue_tab_mode': 'issueEntry',
        'initial_summary': initial_summary,
        'template_summary': initial_summary,
        'clear_summary_on_click': ezt.boolean(
            initial_summary_must_be_edited and
            'initial_summary' not in mr.form_overrides),
        'must_edit_summary': ezt.boolean(initial_summary_must_be_edited),

        'initial_description': wkp.content,
        'template_name': wkp.name,
        'component_required': ezt.boolean(wkp.component_required),
        'initial_status': initial_status,
        'initial_owner': initial_owner_name,
        'owner_avail_state': owner_avail_state,
        'owner_avail_message_short': owner_avail_message_short,
        'initial_components': initial_components,
        'initial_cc': '',
        'initial_blocked_on': '',
        'initial_blocking': '',
        'labels': labels,
        'fields': field_views,

        'any_errors': ezt.boolean(mr.errors.AnyErrors()),
        'page_perms': page_perms,
        'allow_attachments': ezt.boolean(allow_attachments),
        'max_attach_size': template_helpers.BytesKbOrMb(
            framework_constants.MAX_POST_BODY_SIZE),

        'offer_templates': ezt.boolean(offer_templates),
        'config': config_view,

        'restrict_to_known': ezt.boolean(restrict_to_known),
        }

    return page_data