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 testMakeEmailTasks_Starrer(self): """Users who starred the issue are notified iff they opt in.""" issue = fake.MakeTestIssue(789, 1, 'summary', 'New', 0, issue_id=78901) self.services.issue.TestAddIssue(issue) now = int(time.time()) self.SetUpFieldValues(issue, now) issue.project_name = 'proj' comment = self.MakePingComment() next_action_field_def = self.config.field_defs[0] pings = [(next_action_field_def, now)] starrer_333 = self.services.user.TestAddUser('*****@*****.**', 333) starrer_333.notify_starred_ping = True self.services.user.TestAddUser('*****@*****.**', 444) starrer_ids = [333, 444] users_by_id = framework_views.MakeAllUserViews( 'fake cnxn', self.services.user, [self.owner.user_id, self.date_action_user.user_id], starrer_ids) tasks = self.servlet._MakeEmailTasks('fake cnxn', issue, self.project, self.config, comment, starrer_ids, 'example-app.appspot.com', users_by_id, pings) self.assertEqual(1, len(tasks)) notify_owner_task = tasks[0] self.assertEqual('*****@*****.**', notify_owner_task['to'])
def testMakeEmailTasks_Owner(self): """The issue owner gets pinged and the email has expected content.""" issue = fake.MakeTestIssue(789, 1, 'summary', 'New', self.owner.user_id, issue_id=78901) self.services.issue.TestAddIssue(issue) now = int(time.time()) self.SetUpFieldValues(issue, now) issue.project_name = 'proj' comment = self.MakePingComment() next_action_field_def = self.config.field_defs[0] pings = [(next_action_field_def, now)] users_by_id = framework_views.MakeAllUserViews( 'fake cnxn', self.services.user, [self.owner.user_id, self.date_action_user.user_id]) tasks = self.servlet._MakeEmailTasks('fake cnxn', issue, self.project, self.config, comment, [], 'example-app.appspot.com', users_by_id, pings) self.assertEqual(1, len(tasks)) notify_owner_task = tasks[0] self.assertEqual('*****@*****.**', notify_owner_task['to']) self.assertEqual('Follow up on issue 1 in proj: summary', notify_owner_task['subject']) body = notify_owner_task['body'] self.assertIn(comment.content, body) self.assertIn(next_action_field_def.docstring, body)
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 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 BuildProjectMembers(cnxn, project, user_service): """Gather data for the members section of a project page. Args: cnxn: connection to SQL database. project: Project PB of current project. user_service: an instance of UserService for user persistence. Returns: A dictionary suitable for use with EZT. """ # First, get all needed info on all users in one batch of requests. users_by_id = framework_views.MakeAllUserViews( cnxn, user_service, framework_bizobj.AllProjectMembers(project)) # Second, group the user proxies by role for display. owner_proxies = [users_by_id[owner_id] for owner_id in project.owner_ids] committer_proxies = [ users_by_id[committer_id] for committer_id in project.committer_ids ] contributor_proxies = [ users_by_id[contrib_id] for contrib_id in project.contributor_ids ] return { 'owners': owner_proxies, 'committers': committer_proxies, 'contributors': contributor_proxies, 'all_members': users_by_id.values(), }
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 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 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 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 _GetSubscribersAddrPermList(cnxn, services, issue, project, config, omit_addrs, users_by_id): """Lookup subscribers, evaluate their saved queries, and decide to notify.""" users_to_queries = GetNonOmittedSubscriptions(cnxn, services, [project.project_id], omit_addrs) # TODO(jrobbins): need to pass through the user_id to use for "me". subscribers_to_notify = EvaluateSubscriptions(cnxn, issue, users_to_queries, services, config) # TODO(jrobbins): expand any subscribers that are user groups. subs_needing_user_views = [ uid for uid in subscribers_to_notify if uid not in users_by_id ] users_by_id.update( framework_views.MakeAllUserViews(cnxn, services.user, subs_needing_user_views)) sub_addr_perm_list = ComputeIssueChangeAddressPermList( cnxn, subscribers_to_notify, project, issue, services, omit_addrs, users_by_id, pref_check_function=lambda *args: True) return sub_addr_perm_list
def GatherPageData(self, mr): if not mr.auth.user_id: raise permissions.PermissionException( 'Anonymous users are not allowed to download hotlist CSV') owner_id = mr.hotlist.owner_ids[0] # only one owner allowed users_by_id = framework_views.MakeAllUserViews(mr.cnxn, self.services.user, [owner_id]) owner = users_by_id[owner_id] # Try to validate XSRF by either user email or user ID. try: xsrf.ValidateToken( mr.token, mr.auth.user_id, '/u/%s/hotlists/%s.do' % (owner.email, mr.hotlist.name)) except xsrf.TokenIncorrect: xsrf.ValidateToken( mr.token, mr.auth.user_id, '/u/%s/hotlists/%s.do' % (owner.user_id, mr.hotlist.name)) # Sets headers to allow the response to be downloaded. self.content_type = 'text/csv; charset=UTF-8' download_filename = 'hotlist_%d-issues.csv' % mr.hotlist_id self.response.headers.add( 'Content-Disposition', 'attachment; filename=%s' % download_filename) self.response.headers.add('X-Content-Type-Options', 'nosniff') mr.ComputeColSpec(mr.hotlist) mr.col_spec = csv_helpers.RewriteColspec(mr.col_spec) page_data = hotlistissues.HotlistIssues.GatherPageData(self, mr) return csv_helpers.ReformatRowsForCSV(mr, page_data, '%d/csv' % mr.hotlist_id)
def setUp(self): self.mox = mox.Mox() self.mock_index = self.mox.CreateMockAnything() self.mox.StubOutWithMock(search, 'Index') self.docs = None self.cnxn = 'fake connection' self.user_service = fake.UserService() self.user_service.TestAddUser('*****@*****.**', 111) self.issue_service = fake.IssueService() self.config_service = fake.ConfigService() self.issue = fake.MakeTestIssue(123, 1, 'test summary', 'New', 111) self.issue_service.TestAddIssue(self.issue) self.comment = tracker_pb2.IssueComment( project_id=789, issue_id=self.issue.issue_id, user_id=111, content='comment content', attachments=[ tracker_pb2.Attachment(filename='hello.c'), tracker_pb2.Attachment(filename='hello.h') ]) self.issue_service.TestAddComment(self.comment, 1) self.users_by_id = framework_views.MakeAllUserViews( self.cnxn, self.user_service, [111])
def HandleRequest(self, mr): """Process the task to process an issue date action. Args: mr: common information parsed from the HTTP request. Returns: Results dictionary in JSON format which is useful just for debugging. The main goal is the side-effect of sending emails. """ issue_id = mr.GetPositiveIntParam('issue_id') hostport = framework_helpers.GetHostPort() issue = self.services.issue.GetIssue(mr.cnxn, issue_id) project = self.services.project.GetProject(mr.cnxn, issue.project_id) config = self.services.config.GetProjectConfig(mr.cnxn, issue.project_id) pings = self._CalculateIssuePings(issue, config) if not pings: logging.warning('Issue %r has no dates to ping afterall?', issue_id) return comment = self._CreatePingComment(mr.cnxn, issue, pings, hostport) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, tracker_bizobj.UsersInvolvedInIssues([issue]), [comment.user_id]) logging.info('users_by_id is %r', users_by_id) tasks = self._MakeEmailTasks(mr.cnxn, issue, project, config, comment, hostport, users_by_id, pings) notified = notify_helpers.AddAllEmailTasks(tasks) return { 'notified': notified, }
def MakeFieldUserViews(cnxn, template, user_service): """Return {user_id: user_view} for users in template field values.""" field_user_ids = [ fv.user_id for fv in template.field_values if fv.user_id] field_user_views = framework_views.MakeAllUserViews( cnxn, user_service, field_user_ids) return field_user_views
def _ProcessUpstreamIssue( self, cnxn, upstream_issue, upstream_project, upstream_config, issue, omit_ids, hostport, commenter_view): """Compute notifications for one upstream issue that is now blocking.""" upstream_detail_url = framework_helpers.FormatAbsoluteURLForDomain( hostport, upstream_issue.project_name, urls.ISSUE_DETAIL, id=upstream_issue.local_id) logging.info('upstream_detail_url = %r', upstream_detail_url) detail_url = framework_helpers.FormatAbsoluteURLForDomain( hostport, issue.project_name, urls.ISSUE_DETAIL, id=issue.local_id) # Only issues that any contributor could view are sent to mailing lists. contributor_could_view = permissions.CanViewIssue( set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, upstream_project, upstream_issue) # Now construct the e-mail to send # Note: we purposely do not notify users who starred an issue # about changes in blocking. users_by_id = framework_views.MakeAllUserViews( cnxn, self.services.user, tracker_bizobj.UsersInvolvedInIssues([upstream_issue]), omit_ids) is_blocking = upstream_issue.issue_id in issue.blocked_on_iids email_data = { 'issue': tracker_views.IssueView( upstream_issue, users_by_id, upstream_config), 'summary': upstream_issue.summary, 'detail_url': upstream_detail_url, 'is_blocking': ezt.boolean(is_blocking), 'downstream_issue_ref': tracker_bizobj.FormatIssueRef( (None, issue.local_id)), 'downstream_issue_url': detail_url, } # TODO(jrobbins): Generate two versions of email body: members # vesion has other member full email addresses exposed. But, don't # expose too many as we iterate through upstream projects. body_link_only = self.link_only_email_template.GetResponse( {'detail_url': upstream_detail_url, 'was_created': ezt.boolean(False)}) body = self.email_template.GetResponse(email_data) omit_addrs = {users_by_id[omit_id].email for omit_id in omit_ids} # Get the transitive set of owners and Cc'd users, and their UserView's. # Give each user a bullet-list of all the reasons that apply for that user. # Starrers are not notified of blocking changes to reduce noise. group_reason_list = notify_reasons.ComputeGroupReasonList( cnxn, self.services, upstream_project, upstream_issue, upstream_config, users_by_id, omit_addrs, contributor_could_view) one_issue_email_tasks = notify_helpers.MakeBulletedEmailWorkItems( group_reason_list, upstream_issue, body_link_only, body, body, upstream_project, hostport, commenter_view, detail_url) return one_issue_email_tasks
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, component_def = self._GetComponentDef(mr) users_by_id = framework_views.MakeAllUserViews(mr.cnxn, self.services.user, component_def.admin_ids, component_def.cc_ids) component_def_view = tracker_views.ComponentDefView( mr.cnxn, self.services, component_def, users_by_id) initial_admins = [ users_by_id[uid].email for uid in component_def.admin_ids ] initial_cc = [users_by_id[uid].email for uid in component_def.cc_ids] initial_labels = [ self.services.config.LookupLabel(mr.cnxn, mr.project_id, label_id) for label_id in component_def.label_ids ] creator, created = self._GetUserViewAndFormattedTime( mr, component_def.creator_id, component_def.created) modifier, modified = self._GetUserViewAndFormattedTime( mr, component_def.modifier_id, component_def.modified) allow_edit = permissions.CanEditComponentDef(mr.auth.effective_ids, mr.perms, mr.project, component_def, config) subcomponents = tracker_bizobj.FindDescendantComponents( config, component_def) templates = self.services.config.TemplatesWithComponent( mr.cnxn, component_def.component_id, config) allow_delete = allow_edit and not subcomponents and not templates return { 'admin_tab_mode': servlet.Servlet.PROCESS_TAB_COMPONENTS, 'component_def': component_def_view, 'initial_leaf_name': component_def_view.leaf_name, 'initial_docstring': component_def.docstring, 'initial_deprecated': ezt.boolean(component_def.deprecated), 'initial_admins': initial_admins, 'initial_cc': initial_cc, 'initial_labels': initial_labels, 'allow_edit': ezt.boolean(allow_edit), 'allow_delete': ezt.boolean(allow_delete), 'subcomponents': subcomponents, 'templates': templates, 'creator': creator, 'created': created, 'modifier': modifier, 'modified': modified, }
def GatherPageData(self, mr): viewed_users_hotlists = self.services.features.GetHotlistsByUserID( mr.cnxn, mr.viewed_user_auth.user_id) viewed_starred_hids = self.services.hotlist_star.LookupStarredItemIDs( mr.cnxn, mr.viewed_user_auth.user_id) viewed_users_starred_hotlists, _ = self.services.features.GetHotlistsByID( mr.cnxn, viewed_starred_hids) viewed_users_relevant_hotlists = viewed_users_hotlists + list( set(viewed_users_starred_hotlists.values()) - set(viewed_users_hotlists)) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, features_bizobj.UsersInvolvedInHotlists( viewed_users_relevant_hotlists)) views = [ hotlist_views.HotlistView( hotlist_pb, mr.auth, mr.viewed_user_auth.user_id, users_by_id, self.services.hotlist_star.IsItemStarredBy( mr.cnxn, hotlist_pb.hotlist_id, mr.auth.user_id)) for hotlist_pb in viewed_users_relevant_hotlists ] # visible to viewer, not viewed_user visible_hotlists = [view for view in views if view.visible] owner_of_hotlists = [ hotlist_view for hotlist_view in visible_hotlists if hotlist_view.role_name == 'owner' ] editor_of_hotlists = [ hotlist_view for hotlist_view in visible_hotlists if hotlist_view.role_name == 'editor' ] follower_of_hotlists = [ hotlist_view for hotlist_view in visible_hotlists if hotlist_view.role_name == '' ] starred_hotlists = [ hotlist_view for hotlist_view in visible_hotlists if hotlist_view.hotlist_id in viewed_starred_hids ] viewed_user_display_name = framework_views.GetViewedUserDisplayName(mr) return { 'user_tab_mode': 'st6', 'viewed_user_display_name': viewed_user_display_name, 'owner_of_hotlists': owner_of_hotlists, 'editor_of_hotlists': editor_of_hotlists, 'follower_of_hotlists': follower_of_hotlists, 'starred_hotlists': starred_hotlists, 'viewing_user_page': ezt.boolean(True), }
def setUp(self): self.cnxn = 'fake sql connection' self.services = service_manager.Services(project=fake.ProjectService(), user=fake.UserService()) self.services.user.TestAddUser('*****@*****.**', 111) self.services.user.TestAddUser('*****@*****.**', 222) self.services.user.TestAddUser('*****@*****.**', 333) self.users_by_id = framework_views.MakeAllUserViews( 'cnxn', self.services.user, [111, 222, 333]) self.effective_ids_by_user = {user: set() for user in {111, 222, 333}}
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 GetUser(self, mc, request): """Return info about the specified user.""" with work_env.WorkEnv(mc, self.services) as we: users, linked_user_ids = we.ListReferencedUsers( [request.user_ref.display_name]) linked_user_views = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, linked_user_ids) with mc.profiler.Phase('converting to response objects'): response_users = converters.ConvertUsers(users, linked_user_views) return response_users[0]
def GetVisibleMembers(mr, project, services): all_member_ids = framework_bizobj.AllProjectMembers(project) all_group_ids = services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, all_member_ids) (ac_exclusion_ids, no_expand_ids) = services.project.GetProjectAutocompleteExclusion( mr.cnxn, project.project_id) group_ids_to_expand = [ gid for gid in all_group_ids if gid not in no_expand_ids ] # TODO(jrobbins): Normally, users will be allowed view the members # of any user group if the project From: email address is listed # as a group member, as well as any group that they are personally # members of. member_ids, owner_ids = services.usergroup.LookupVisibleMembers( mr.cnxn, group_ids_to_expand, mr.perms, mr.auth.effective_ids, services) indirect_user_ids = set() for gids in member_ids.values(): indirect_user_ids.update(gids) for gids in owner_ids.values(): indirect_user_ids.update(gids) visible_member_ids = _FilterMemberData(mr, project.owner_ids, project.committer_ids, project.contributor_ids, indirect_user_ids, project) visible_member_ids = _MergeLinkedMembers(mr.cnxn, services.user, visible_member_ids) visible_member_views = framework_views.MakeAllUserViews( mr.cnxn, services.user, visible_member_ids, group_ids=all_group_ids) # Filter out service accounts service_acct_emails = set( client_config_svc.GetClientConfigSvc().GetClientIDEmails()[1]) visible_member_views = { m.user_id: m for m in visible_member_views.values() if not framework_helpers.IsServiceAccount( m.email, client_emails=service_acct_emails) and not m.user_id in ac_exclusion_ids } return visible_member_views
def GetMemberships(self, mc, request): """Return the user groups for the given user visible to the requester.""" user_id = converters.IngestUserRef(mc.cnxn, request.user_ref, self.services.user) with work_env.WorkEnv(mc, self.services) as we: group_ids = we.GetMemberships(user_id) with mc.profiler.Phase('converting to response objects'): groups_by_id = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, group_ids) group_refs = converters.ConvertUserRefs(group_ids, [], groups_by_id, True) return users_pb2.GetMembershipsResponse(group_refs=group_refs)
def ListReferencedUsers(self, mc, request): """Return the list of existing users in a response proto.""" emails = request.emails if request.user_refs: emails = [user_ref.display_name for user_ref in request.user_refs] with work_env.WorkEnv(mc, self.services) as we: users, linked_user_ids = we.ListReferencedUsers(emails) linked_user_views = framework_views.MakeAllUserViews( mc.cnxn, self.services.user, linked_user_ids) with mc.profiler.Phase('converting to response objects'): response_users = converters.ConvertUsers(users, linked_user_views) response = users_pb2.ListReferencedUsersResponse(users=response_users) return response
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 setUp(self): self.services = service_manager.Services(user=fake.UserService(), config=fake.ConfigService()) self.services.user.TestAddUser('*****@*****.**', 111) self.services.user.TestAddUser('*****@*****.**', 222) self.users_by_id = framework_views.MakeAllUserViews( 'cnxn', self.services.user, [111, 222]) self.services.config.TestAddLabelsDict({'Hot': 1, 'Cold': 2}) self.cd = tracker_bizobj.MakeComponentDef(10, 789, 'UI', 'User interface', False, [111], [222], 0, 111, label_ids=[1, 2])
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