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'], '')
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'], [])
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))
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))
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'])
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'])
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
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
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