def CheckRevealAllToMember( self, logged_in_user_id, expected, viewed_user_id=333, group_id=None): user_view = framework_views.StuffUserView( viewed_user_id, '*****@*****.**', True) if group_id: pass # xxx re-implement groups users_by_id = {333: user_view} self.mr.auth.user_id = logged_in_user_id self.mr.auth.effective_ids = {logged_in_user_id} # Assert display name is obscured before the reveal. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url contains user ID before the reveal. self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) framework_views.RevealAllEmailsToMembers( self.mr.auth, self.mr.project, users_by_id) self.assertEqual(expected, not user_view.obscure_email) if expected: # Assert display name is now revealed. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url contains the email. self.assertEqual('/u/[email protected]/', user_view.profile_url) else: # Assert display name is still hidden. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url still contains user ID. self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url)
def ListIssues(self, mc, request): """Return the list of issues for projects that satisfy the given query.""" use_cached_searches = not settings.local_mode # TODO(zhangtiff): Rework FrontendSearchPipeline to not depend on url_params # for can. can = request.canned_query or 1 with work_env.WorkEnv(mc, self.services) as we: start, max_items = converters.IngestPagination(request.pagination) pipeline = we.ListIssues(request.query, request.project_names, mc.auth.user_id, max_items, start, [('can', can)], can, request.group_by_spec, request.sort_spec, use_cached_searches) with mc.profiler.Phase('reveal emails to members'): projects = self.services.project.GetProjectsByName( mc.cnxn, request.project_names) for _, p in projects.items(): framework_views.RevealAllEmailsToMembers( mc.auth, p, pipeline.users_by_id) converted_results = [] with work_env.WorkEnv(mc, self.services) as we: for issue in pipeline.visible_results: related_refs = we.GetRelatedIssueRefs([issue]) converted_results.append( converters.ConvertIssue(issue, pipeline.users_by_id, related_refs, pipeline.harmonized_config)) return issues_pb2.ListIssuesResponse( issues=converted_results, total_results=pipeline.pagination.total_count)
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
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
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
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
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
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
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
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
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), }
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 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
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
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
def UpdateApproval(self, mc, request): """Update an approval and return the updated approval in a reponse proto.""" project, issue, config = self._GetProjectIssueAndConfig( mc, request.issue_ref, use_cache=False) approval_fd = tracker_bizobj.FindFieldDef(request.field_ref.field_name, config) if not approval_fd: raise exceptions.NoSuchFieldDefException() if request.HasField('approval_delta'): approval_delta = converters.IngestApprovalDelta( mc.cnxn, self.services.user, request.approval_delta, mc.auth.user_id, config) else: approval_delta = tracker_pb2.ApprovalDelta() attachments = converters.IngestAttachmentUploads(request.uploads) with work_env.WorkEnv(mc, self.services) as we: av, _comment = we.UpdateIssueApproval( issue.issue_id, approval_fd.field_id, approval_delta, request.comment_content, request.is_description, attachments=attachments, send_email=request.send_email, kept_attachments=list(request.kept_attachments)) with mc.profiler.Phase('converting to response objects'): users_by_id = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, av.approver_ids, [av.setter_id]) framework_views.RevealAllEmailsToMembers(mc.auth, project, users_by_id) response = issues_pb2.UpdateApprovalResponse() response.approval.CopyFrom( converters.ConvertApproval(av, users_by_id, config)) return response
def ListComponents(self, mc, request): """Return all component defs in the specified project.""" 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_by_id = {} if request.include_admin_info: 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) with mc.profiler.Phase('looking up labels'): labels_by_id = {} if request.include_admin_info: 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 } component_defs = [ converters.ConvertComponentDef(cd, users_by_id, labels_by_id, request.include_admin_info) for cd in config.component_defs ] result = projects_pb2.ListComponentsResponse( component_defs=component_defs) return result
def UpdateIssue(self, mc, request): """Apply a delta and comment to the specified issue, then return it.""" project, issue, config = self._GetProjectIssueAndConfig( mc, request.issue_ref, use_cache=False) with work_env.WorkEnv(mc, self.services) as we: if request.HasField('delta'): delta = converters.IngestIssueDelta(mc.cnxn, self.services, request.delta, config, issue.phases) else: delta = tracker_pb2.IssueDelta() # No changes specified. attachments = converters.IngestAttachmentUploads(request.uploads) we.UpdateIssue(issue, delta, request.comment_content, send_email=request.send_email, attachments=attachments, is_description=request.is_description, kept_attachments=list(request.kept_attachments)) 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
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(AdminComponents, self).GatherPageData(mr) config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, *[ list(cd.admin_ids) + list(cd.cc_ids) for cd in config.component_defs ]) framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id) component_def_views = [ tracker_views.ComponentDefView(mr.cnxn, self.services, cd, users_by_id) # TODO(jrobbins): future component-level view restrictions. for cd in config.component_defs ] for cd in component_def_views: if mr.auth.email in [user.email for user in cd.admins]: cd.classes += 'myadmin ' if mr.auth.email in [user.email for user in cd.cc]: cd.classes += 'mycc ' page_data.update({ 'component_defs': component_def_views, 'failed_perm': mr.GetParam('failed_perm'), 'failed_subcomp': mr.GetParam('failed_subcomp'), 'failed_templ': mr.GetParam('failed_templ'), }) return page_data
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. """ search_error_message = '' with work_env.WorkEnv(mr, self.services) as we: # Check if the user's query is just the ID of an existing issue. # TODO(jrobbins): consider implementing this for cross-project search. if mr.project and tracker_constants.JUMP_RE.match(mr.query): local_id = int(mr.query) try: we.GetIssueByLocalID(mr.project_id, local_id) # does it exist? url = framework_helpers.FormatAbsoluteURL( mr, urls.ISSUE_DETAIL, id=local_id) self.redirect(url, abort=True) # Jump to specified issue. except exceptions.NoSuchIssueException: pass # The user is searching for a number that is not an issue ID. with mr.profiler.Phase('finishing config work'): if mr.project_id: config = we.GetProjectConfig(mr.project_id) else: config = tracker_bizobj.MakeDefaultProjectIssueConfig(None) url_params = [(name, mr.GetParam(name)) for name in framework_helpers.RECOGNIZED_PARAMS] pipeline = we.ListIssues( mr.query, mr.query_project_names, mr.me_user_id, mr.num, mr.start, url_params, mr.can, mr.group_by_spec, mr.sort_spec, mr.use_cached_searches, display_mode=mr.mode, project=mr.project) starred_iid_set = set(we.ListStarredIssueIDs()) with mr.profiler.Phase('computing col_spec'): mr.ComputeColSpec(config) with mr.profiler.Phase('publishing emails'): framework_views.RevealAllEmailsToMembers( mr.auth, mr.project, pipeline.users_by_id) with mr.profiler.Phase('getting related issues'): related_iids = set() if pipeline.grid_mode: results_needing_related = pipeline.allowed_results or [] else: results_needing_related = pipeline.visible_results or [] lower_cols = mr.col_spec.lower().split() lower_cols.extend(mr.group_by_spec.lower().split()) grid_x = (mr.x or config.default_x_attr or '--').lower() grid_y = (mr.y or config.default_y_attr or '--').lower() lower_cols.append(grid_x) lower_cols.append(grid_y) for issue in results_needing_related: if 'blockedon' in lower_cols: related_iids.update(issue.blocked_on_iids) if 'blocking' in lower_cols: related_iids.update(issue.blocking_iids) if 'mergedinto' in lower_cols: related_iids.add(issue.merged_into) related_issues_list = self.services.issue.GetIssues( mr.cnxn, list(related_iids)) related_issues = {issue.issue_id: issue for issue in related_issues_list} with mr.profiler.Phase('filtering unviewable issues'): viewable_iids_set = {issue.issue_id for issue in tracker_helpers.GetAllowedIssues( mr, [related_issues.values()], self.services)[0]} with mr.profiler.Phase('building table/grid'): if pipeline.grid_mode: # TODO(eyalsoha): Add viewable_iids_set to the grid so that referenced # issues can be links. page_data = grid_view_helpers.GetGridViewData( mr, pipeline.allowed_results or [], pipeline.harmonized_config, pipeline.users_by_id, starred_iid_set, pipeline.grid_limited, related_issues) else: page_data = self.GetTableViewData( mr, pipeline.visible_results or [], pipeline.harmonized_config, pipeline.users_by_id, starred_iid_set, related_issues, viewable_iids_set) # We show a special message when no query will every produce any results # because the project has no issues in it. with mr.profiler.Phase('starting stars promise'): if mr.project_id: project_has_any_issues = ( pipeline.allowed_results or self.services.issue.GetHighestLocalID(mr.cnxn, mr.project_id) != 0) else: project_has_any_issues = True # Message only applies in a project. with mr.profiler.Phase('making page perms'): page_perms = self.MakePagePerms( mr, None, permissions.SET_STAR, permissions.CREATE_ISSUE, permissions.EDIT_ISSUE) if pipeline.error_responses: search_error_message = ( '%d search backends did not respond or had errors. ' 'These results are probably incomplete.' % len(pipeline.error_responses)) # Update page data with variables that are shared between list and # grid view. user_hotlists = self.services.features.GetHotlistsByUserID( mr.cnxn, mr.auth.user_id) new_ui_url = '' if hasattr(self.request, 'url'): new_ui_url = self.request.url.replace('issues/list', 'issues/list_new') # monorail:6336, needed for <ezt-show-columns-connector> phase_names = _GetAllPhaseNames(pipeline.visible_results) page_data.update({ 'issue_tab_mode': 'issueList', 'pagination': pipeline.pagination, 'is_cross_project': ezt.boolean(len(pipeline.query_project_ids) != 1), 'project_has_any_issues': ezt.boolean(project_has_any_issues), 'colspec': mr.col_spec, # monorail:6336, used in <ezt-show-columns-connector> 'phasespec': " ".join(phase_names), 'page_perms': page_perms, 'grid_mode': ezt.boolean(pipeline.grid_mode), 'list_mode': ezt.boolean(pipeline.list_mode), 'chart_mode': ezt.boolean(pipeline.chart_mode), 'panel_id': mr.panel_id, 'search_error_message': search_error_message, 'is_hotlist': ezt.boolean(False), # for update-issues-hotlists-dialog, user_remininag_hotlists # are displayed with their checkboxes unchecked. 'user_remaining_hotlists': user_hotlists, 'user_issue_hotlists': [], # for update-issues-hotlsits-dialog # the following are needed by templates for hotlists 'owner_permissions': ezt.boolean(False), 'editor_permissions': ezt.boolean(False), 'edit_hotlist_token': '', 'add_local_ids': '', 'placeholder': '', 'col_spec': '', 'new_ui_url': new_ui_url, }) return page_data
def GatherUpdatesData(services, mr, project_ids=None, user_ids=None, ending=None, updates_page_url=None, autolink=None, highlight=None): """Gathers and returns updates data. Args: services: Connections to backend services. mr: HTTP request info, used by the artifact autolink. project_ids: List of project IDs we want updates for. user_ids: List of user IDs we want updates for. ending: Ending type for activity titles, 'in_project' or 'by_user'. updates_page_url: The URL that will be used to create pagination links from. autolink: Autolink instance. highlight: What to highlight in the middle column on user updates pages i.e. 'project', 'user', or None. """ # num should be non-negative number num = mr.GetPositiveIntParam('num', UPDATES_PER_PAGE) num = min(num, MAX_UPDATES_PER_PAGE) updates_data = { 'no_stars': None, 'no_activities': None, 'pagination': None, 'updates_data': None, 'ending_type': ending, } if not user_ids and not project_ids: updates_data['no_stars'] = ezt.boolean(True) return updates_data ascending = bool(mr.after) with mr.profiler.Phase('get activities'): comments = services.issue.GetIssueActivity(mr.cnxn, num=num, before=mr.before, after=mr.after, project_ids=project_ids, user_ids=user_ids, ascending=ascending) # Filter the comments based on permission to view the issue. # TODO(jrobbins): push permission checking in the query so that # pagination pages never become underfilled, or use backends to shard. # TODO(jrobbins): come back to this when I implement private comments. # TODO(jrobbins): it would be better if we could just get the dict directly. prefetched_issues_list = services.issue.GetIssues( mr.cnxn, {c.issue_id for c in comments}) prefetched_issues = { issue.issue_id: issue for issue in prefetched_issues_list } needed_project_ids = { issue.project_id for issue in prefetched_issues_list } prefetched_projects = services.project.GetProjects( mr.cnxn, needed_project_ids) prefetched_configs = services.config.GetProjectConfigs( mr.cnxn, needed_project_ids) viewable_issues_list = tracker_helpers.FilterOutNonViewableIssues( mr.auth.effective_ids, mr.auth.user_pb, prefetched_projects, prefetched_configs, prefetched_issues_list) viewable_iids = {issue.issue_id for issue in viewable_issues_list} comments = [c for c in comments if c.issue_id in viewable_iids] if ascending: comments.reverse() amendment_user_ids = [] for comment in comments: for amendment in comment.amendments: amendment_user_ids.extend(amendment.added_user_ids) amendment_user_ids.extend(amendment.removed_user_ids) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, services.user, [c.user_id for c in comments], amendment_user_ids) framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id) num_results_returned = len(comments) displayed_activities = comments[:UPDATES_PER_PAGE] if not num_results_returned: updates_data['no_activities'] = ezt.boolean(True) return updates_data # Get all referenced artifacts first all_ref_artifacts = None if autolink is not None: content_list = [] for activity in comments: content_list.append(activity.content) all_ref_artifacts = autolink.GetAllReferencedArtifacts( mr, content_list) # Now process content and gather activities today = [] yesterday = [] pastweek = [] pastmonth = [] thisyear = [] older = [] with mr.profiler.Phase('rendering activities'): for activity in displayed_activities: entry = ActivityView(activity, mr, prefetched_issues, users_by_id, prefetched_projects, prefetched_configs, autolink=autolink, all_ref_artifacts=all_ref_artifacts, ending=ending, highlight=highlight) if entry.date_bucket == 'Today': today.append(entry) elif entry.date_bucket == 'Yesterday': yesterday.append(entry) elif entry.date_bucket == 'Last 7 days': pastweek.append(entry) elif entry.date_bucket == 'Last 30 days': pastmonth.append(entry) elif entry.date_bucket == 'Earlier this year': thisyear.append(entry) elif entry.date_bucket == 'Before this year': older.append(entry) new_after = None new_before = None if displayed_activities: new_after = displayed_activities[0].timestamp new_before = displayed_activities[-1].timestamp prev_url = None next_url = None if updates_page_url: list_servlet_rel_url = updates_page_url.split('/')[-1] recognized_params = [(name, mr.GetParam(name)) for name in framework_helpers.RECOGNIZED_PARAMS] if displayed_activities and (mr.before or mr.after): prev_url = framework_helpers.FormatURL(recognized_params, list_servlet_rel_url, after=new_after) if mr.after or len(comments) > UPDATES_PER_PAGE: next_url = framework_helpers.FormatURL(recognized_params, list_servlet_rel_url, before=new_before) if prev_url or next_url: pagination = template_helpers.EZTItem(start=None, last=None, prev_url=prev_url, next_url=next_url, reload_url=None, visible=ezt.boolean(True), total_count=None) else: pagination = None updates_data.update({ 'no_activities': ezt.boolean(False), 'pagination': pagination, 'updates_data': template_helpers.EZTItem(today=today, yesterday=yesterday, pastweek=pastweek, pastmonth=pastmonth, thisyear=thisyear, older=older), }) return updates_data
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. """ if mr.local_id is None: self.abort(404, 'no issue specified') with work_env.WorkEnv(mr, self.services) as we: # Signed in users could edit the issue, so it must be fresh. use_cache = not mr.auth.user_id issue = we.GetIssueByLocalID( mr.project_id, mr.local_id, use_cache=use_cache) # We give no explanation of missing issues on the peek page. if issue.deleted: self.abort(404, 'issue not found') star_cnxn = sql.MonorailConnection() star_promise = framework_helpers.Promise( we.IsIssueStarred, issue, cnxn=star_cnxn) config = we.GetProjectConfig(mr.project_id) comments = we.ListIssueComments(issue) descriptions, visible_comments, cmnt_pagination = PaginateComments( mr, issue, comments, config, self.services) with mr.profiler.Phase('making user proxies'): involved_user_ids = tracker_bizobj.UsersInvolvedInIssues([issue]) group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, involved_user_ids) comment_user_ids = tracker_bizobj.UsersInvolvedInCommentList( descriptions + visible_comments) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, involved_user_ids, comment_user_ids, group_ids=group_ids) framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id) (issue_view, description_views, comment_views) = self._MakeIssueAndCommentViews( mr, issue, users_by_id, descriptions, visible_comments, config, issue_reporters=[], comment_reporters=[]) with mr.profiler.Phase('getting starring info'): starred = star_promise.WaitAndGetValue() star_cnxn.Close() permit_edit = permissions.CanEditIssue( mr.auth.effective_ids, mr.perms, mr.project, issue) mr.ComputeColSpec(config) restrict_to_known = config.restrict_to_known page_perms = self.MakePagePerms( mr, issue, 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, permissions.DELETE_ISSUE, permissions.ADD_ISSUE_COMMENT, permissions.DELETE_OWN, permissions.DELETE_ANY, permissions.VIEW_INBOUND_MESSAGES) page_perms.EditIssue = ezt.boolean(permit_edit) prevent_restriction_removal = ( mr.project.only_owners_remove_restrictions and not framework_bizobj.UserOwnsProject( mr.project, mr.auth.effective_ids)) cmd_slots, default_slot_num = self.services.features.GetRecentCommands( mr.cnxn, mr.auth.user_id, mr.project_id) cmd_slot_views = [ template_helpers.EZTItem( slot_num=slot_num, command=command, comment=comment) for slot_num, command, comment in cmd_slots] previous_locations = self.GetPreviousLocations(mr, issue) return { 'issue_tab_mode': 'issueDetail', 'issue': issue_view, 'description': description_views, 'comments': comment_views, 'labels': issue.labels, 'num_detail_rows': len(comment_views) + 4, 'noisy': ezt.boolean(tracker_helpers.IsNoisy( len(comment_views), issue.star_count)), 'cmnt_pagination': cmnt_pagination, 'colspec': mr.col_spec, 'searchtip': 'You can jump to any issue by number', 'starred': ezt.boolean(starred), 'pagegen': str(int(time.time() * 1000000)), 'restrict_to_known': ezt.boolean(restrict_to_known), 'prevent_restriction_removal': ezt.boolean( prevent_restriction_removal), 'statuses_offer_merge': config.statuses_offer_merge, 'page_perms': page_perms, 'cmd_slots': cmd_slot_views, 'default_slot_num': default_slot_num, 'quick_edit_submit_url': tracker_helpers.FormatRelativeIssueURL( issue.project_name, urls.ISSUE_PEEK + '.do', id=issue.local_id), 'previous_locations': previous_locations, # for template issue-meta-part shared by issuedetail servlet 'user_remaining_hotlists': [], 'user_issue_hotlists': [], 'involved_users_issue_hotlists': [], 'remaining_issue_hotlists': [], }
def CheckRevealAllToMember( self, logged_in_user_id, expected, viewed_user_id=333L, group_id=None): user_view = framework_views.StuffUserView( viewed_user_id, '*****@*****.**', True) if group_id: pass # xxx re-implement groups users_by_id = {333L: user_view} self.mr.auth.user_id = logged_in_user_id self.mr.auth.effective_ids = {logged_in_user_id} # Assert display name is obscured before the reveal. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url contains user ID before the reveal. self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) framework_views.RevealAllEmailsToMembers(self.mr, users_by_id) self.assertEqual(expected, not user_view.obscure_email) if expected: # Assert display name is now revealed. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url contains the email. self.assertEqual('/u/[email protected]/', user_view.profile_url) else: # Assert display name is still hidden. self.assertEqual('*****@*****.**', user_view.display_name) # Assert profile url still contains user ID. self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) def testRevealEmailsToPriviledgedDomain(self): for priviledged_user_domain in settings.priviledged_user_domains: self.mr.auth.user_pb.email = 'test@' + priviledged_user_domain
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page.""" all_members = (mr.project.owner_ids + mr.project.committer_ids + mr.project.contributor_ids) 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) # TODO(jrobbins): re-implement FindUntrustedGroups() untrusted_user_group_proxies = [] with self.profiler.Phase('gathering commitments (notes)'): project_commitments = self.services.project.GetProjectCommitments( mr.cnxn, mr.project_id) with self.profiler.Phase('gathering autocomple exclusion ids'): acexclusion_ids = self.services.project.GetProjectAutocompleteExclusion( mr.cnxn, mr.project_id) with self.profiler.Phase('making member views'): owner_views = self._MakeMemberViews(mr.auth.user_id, users_by_id, mr.project.owner_ids, mr.project, project_commitments, acexclusion_ids) committer_views = self._MakeMemberViews( mr.auth.user_id, users_by_id, mr.project.committer_ids, mr.project, project_commitments, acexclusion_ids) contributor_views = self._MakeMemberViews( mr.auth.user_id, users_by_id, mr.project.contributor_ids, mr.project, project_commitments, acexclusion_ids) all_member_views = owner_views + committer_views + contributor_views pagination = paginate.ArtifactPagination(mr, all_member_views, MEMBERS_PER_PAGE, urls.PEOPLE_LIST) offer_membership_editing = mr.perms.HasPerm(permissions.EDIT_PROJECT, mr.auth.user_id, mr.project) check_abandonment = permissions.ShouldCheckForAbandonment(mr) newly_added_views = [ mv for mv in all_member_views if str(mv.user.user_id) in mr.GetParam('new', []) ] return { 'pagination': pagination, 'subtab_mode': None, 'offer_membership_editing': ezt.boolean(offer_membership_editing), 'initial_add_members': '', 'initially_expand_form': ezt.boolean(False), 'untrusted_user_groups': untrusted_user_group_proxies, 'check_abandonment': ezt.boolean(check_abandonment), 'total_num_owners': len(mr.project.owner_ids), 'newly_added_views': newly_added_views, 'is_hotlist': ezt.boolean(False), }
def ListActivities(self, mc, request): """Return issue activities by a specified user in a response proto.""" converted_user = converters.IngestUserRef(mc.cnxn, request.user_ref, self.services.user) user = self.services.user.GetUser(mc.cnxn, converted_user) comments = self.services.issue.GetIssueActivity( mc.cnxn, user_ids={request.user_ref.user_id}) issues = self.services.issue.GetIssues(mc.cnxn, {c.issue_id for c in comments}) project_dict = tracker_helpers.GetAllIssueProjects( mc.cnxn, issues, self.services.project) config_dict = self.services.config.GetProjectConfigs( mc.cnxn, list(project_dict.keys())) allowed_issues = tracker_helpers.FilterOutNonViewableIssues( mc.auth.effective_ids, user, project_dict, config_dict, issues) issue_dict = {issue.issue_id: issue for issue in allowed_issues} comments = [c for c in comments if c.issue_id in issue_dict] users_by_id = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, [request.user_ref.user_id], tracker_bizobj.UsersInvolvedInCommentList(comments)) for project in project_dict.values(): framework_views.RevealAllEmailsToMembers(mc.auth, project, users_by_id) issues_by_project = {} for issue in allowed_issues: issues_by_project.setdefault(issue.project_id, []).append(issue) # A dictionary {issue_id: perms} of the PermissionSet for the current user # on each of the issues. issue_perms_dict = {} # A dictionary {comment_id: [reporter_id]} of users who have reported the # comment as spam. comment_reporters = {} for project_id, project_issues in issues_by_project.items(): mc.LookupLoggedInUserPerms(project_dict[project_id]) issue_perms_dict.update({ issue.issue_id: permissions.UpdateIssuePermissions( mc.perms, project_dict[issue.project_id], issue, mc.auth.effective_ids, config=config_dict[issue.project_id]) for issue in project_issues }) with work_env.WorkEnv(mc, self.services) as we: project_issue_reporters = we.LookupIssuesFlaggers( project_issues) for _, issue_comment_reporters in project_issue_reporters.values( ): comment_reporters.update(issue_comment_reporters) with mc.profiler.Phase('converting to response objects'): converted_comments = [] for c in comments: issue = issue_dict.get(c.issue_id) issue_perms = issue_perms_dict.get(c.issue_id) result = converters.ConvertComment( issue, c, config_dict.get(issue.project_id), users_by_id, comment_reporters.get(c.id, []), {c.id: 1} if c.is_description else {}, mc.auth.user_id, issue_perms) converted_comments.append(result) converted_issues = [ issue_objects_pb2.IssueSummary(project_name=issue.project_name, local_id=issue.local_id, summary=issue.summary) for issue in allowed_issues ] response = issues_pb2.ListActivitiesResponse( comments=converted_comments, issue_summaries=converted_issues) return response
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page.""" member_id = self.ValidateMemberID(mr.cnxn, mr.specified_user_id, mr.project) group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, [member_id]) users_by_id = framework_views.MakeAllUserViews(mr.cnxn, self.services.user, [member_id]) framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id) project_commitments = self.services.project.GetProjectCommitments( mr.cnxn, mr.project_id) (ac_exclusion_ids, no_expand_ids ) = self.services.project.GetProjectAutocompleteExclusion( mr.cnxn, mr.project_id) member_view = project_views.MemberView( mr.auth.user_id, member_id, users_by_id[member_id], mr.project, project_commitments, ac_exclusion=(member_id in ac_exclusion_ids), no_expand=(member_id in no_expand_ids), is_group=(member_id in group_ids)) member_user = self.services.user.GetUser(mr.cnxn, member_id) # This ignores indirect memberships, which is ok because we are viewing # the page for a member directly involved in the project role_perms = permissions.GetPermissions(member_user, {member_id}, mr.project) # TODO(jrobbins): clarify in the UI which permissions are built-in to # the user's direct role, vs. which are granted via a group membership, # vs. which ones are extra_perms that have been added specifically for # this user. member_perms = template_helpers.EZTItem() for perm in CHECKBOX_PERMS: setattr( member_perms, perm, ezt.boolean(role_perms.HasPerm(perm, member_id, mr.project))) displayed_extra_perms = [ perm for perm in member_view.extra_perms if perm not in CHECKBOX_PERMS ] viewing_self = mr.auth.user_id == member_id warn_abandonment = (viewing_self and permissions.ShouldCheckForAbandonment(mr)) return { 'subtab_mode': None, 'member': member_view, 'role_perms': role_perms, 'member_perms': member_perms, 'displayed_extra_perms': displayed_extra_perms, 'offer_edit_perms': ezt.boolean(self.CanEditPerms(mr)), 'offer_edit_member_notes': ezt.boolean(self.CanEditMemberNotes(mr, member_id)), 'offer_remove_role': ezt.boolean(self.CanRemoveRole(mr, member_id)), 'expand_perms': ezt.boolean(mr.auth.user_pb.keep_people_perms_open), 'warn_abandonment': ezt.boolean(warn_abandonment), 'total_num_owners': len(mr.project.owner_ids), }
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 = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) template = self.services.template.GetTemplateByName( mr.cnxn, mr.template_name, mr.project_id) template_view = tracker_views.IssueTemplateView( mr, template, self.services.user, config) with mr.profiler.Phase('making user views'): users_involved = tracker_bizobj.UsersInvolvedInTemplate(template) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, users_involved) framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id) 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 } non_masked_labels = tracker_bizobj.NonMaskedLabels( template.labels, field_name_set) field_views = tracker_views.MakeAllFieldValueViews( config, template.labels, [], template.field_values, users_by_id, phases=template.phases) (prechecked_approvals, required_approval_ids, initial_phases) = template_helpers.GatherApprovalsPageData( template.approval_values, template.phases, config) allow_edit = permissions.CanEditTemplate(mr.auth.effective_ids, mr.perms, mr.project, template) return { 'admin_tab_mode': self._PROCESS_SUBTAB, 'allow_edit': ezt.boolean(allow_edit), 'new_template_form': ezt.boolean(False), 'initial_members_only': template_view.members_only, 'template_name': template_view.name, 'initial_summary': template_view.summary, 'initial_must_edit_summary': template_view.summary_must_be_edited, 'initial_content': template_view.content, 'initial_status': template_view.status, 'initial_owner': template_view.ownername, 'initial_owner_defaults_to_member': template_view.owner_defaults_to_member, 'initial_components': template_view.components, 'initial_component_required': template_view.component_required, 'fields': [ view for view in field_views if view.field_def.type_name is not 'APPROVAL_TYPE' ], 'initial_add_approvals': ezt.boolean(prechecked_approvals), 'initial_phases': initial_phases, 'approvals': [ view for view in field_views if view.field_def.type_name is 'APPROVAL_TYPE' ], 'prechecked_approvals': prechecked_approvals, 'required_approval_ids': required_approval_ids, 'labels': non_masked_labels, 'initial_admins': template_view.admin_names, }