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 HandleRequest(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 not mr.start and not mr.num: issues = self.services.issue.GetAllIssuesInProject( mr.cnxn, mr.project.project_id) else: local_id_range = range(mr.start, mr.start + mr.num) issues = self.services.issue.GetIssuesByLocalIDs( mr.cnxn, mr.project.project_id, local_id_range) user_id_set = tracker_bizobj.UsersInvolvedInIssues(issues) comments_dict = self.services.issue.GetCommentsForIssues( mr.cnxn, [issue.issue_id for issue in issues]) for comment_list in comments_dict.itervalues(): user_id_set.update( tracker_bizobj.UsersInvolvedInCommentList(comment_list)) starrers_dict = self.services.issue_star.LookupItemsStarrers( mr.cnxn, [issue.issue_id for issue in issues]) for starrer_id_list in starrers_dict.itervalues(): user_id_set.update(starrer_id_list) # The value 0 indicates "no user", e.g., that an issue has no owner. # We don't need to create a User row to represent that. user_id_set.discard(0) email_dict = self.services.user.LookupUserEmails(mr.cnxn, user_id_set) issues_json = [ self._MakeIssueJSON(mr, issue, email_dict, comments_dict.get(issue.issue_id, []), starrers_dict.get(issue.issue_id, [])) for issue in issues if not issue.deleted ] json_data = { 'metadata': { 'version': 1, 'when': int(time.time()), 'who': mr.auth.email, 'project': mr.project_name, 'start': mr.start, 'num': mr.num, }, 'issues': issues_json, # This list could be derived from the 'issues', but we provide it for # ease of processing. 'emails': email_dict.values(), } return json_data
def testUsersInvolvedInCommentList(self): self.assertEqual(set(), tracker_bizobj.UsersInvolvedInCommentList([])) c1 = tracker_pb2.IssueComment() c1.user_id = 111L c1.amendments.append(tracker_pb2.Amendment(newvalue='foo')) c2 = tracker_pb2.IssueComment() c2.user_id = 111L c2.amendments.append(tracker_pb2.Amendment( added_user_ids=[222L], removed_user_ids=[333L])) self.assertEqual({111L}, tracker_bizobj.UsersInvolvedInCommentList([c1])) self.assertEqual({111L, 222L, 333L}, tracker_bizobj.UsersInvolvedInCommentList([c2])) self.assertEqual({111L, 222L, 333L}, tracker_bizobj.UsersInvolvedInCommentList([c1, c2]))
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 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 HandleRequest(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.query or mr.can != 1: with work_env.WorkEnv(mr, self.services) as we: url_params = [] pipeline = we.ListIssues(mr.query, [mr.project.project_name], mr.auth.user_id, mr.num, mr.start, url_params, mr.can, mr.group_by_spec, mr.sort_spec, False) issues = pipeline.allowed_results # no user query and mr.can == 1 (we want all issues) elif not mr.start and not mr.num: issues = self.services.issue.GetAllIssuesInProject( mr.cnxn, mr.project.project_id) else: local_id_range = list(range(mr.start, mr.start + mr.num)) issues = self.services.issue.GetIssuesByLocalIDs( mr.cnxn, mr.project.project_id, local_id_range) user_id_set = tracker_bizobj.UsersInvolvedInIssues(issues) comments_dict = self.services.issue.GetCommentsForIssues( mr.cnxn, [issue.issue_id for issue in issues]) for comment_list in comments_dict.values(): user_id_set.update( tracker_bizobj.UsersInvolvedInCommentList(comment_list)) starrers_dict = self.services.issue_star.LookupItemsStarrers( mr.cnxn, [issue.issue_id for issue in issues]) for starrer_id_list in starrers_dict.values(): user_id_set.update(starrer_id_list) # The value 0 indicates "no user", e.g., that an issue has no owner. # We don't need to create a User row to represent that. user_id_set.discard(0) email_dict = self.services.user.LookupUserEmails(mr.cnxn, user_id_set, ignore_missed=True) issues_json = [ self._MakeIssueJSON(mr, issue, email_dict, comments_dict.get(issue.issue_id, []), starrers_dict.get(issue.issue_id, [])) for issue in issues if not issue.deleted ] json_data = { 'metadata': { 'version': 1, 'when': int(time.time()), 'who': mr.auth.email, 'project': mr.project_name, 'start': mr.start, 'num': mr.num, }, 'issues': issues_json, # This list could be derived from the 'issues', but we provide it for # ease of processing. 'emails': list(email_dict.values()), } return json_data