def _BuildRestrictionChoices(project, freq_restrictions, actions): """Return a list of autocompletion choices for restriction labels. Args: project: Project PB for the current project. freq_restrictions: list of (action, perm, doc) tuples for restrictions that are frequently used. actions: list of strings for actions that are relevant to the current artifact. Returns: A list of dictionaries [{'name': 'perm name', 'doc': 'docstring'}, ...] suitable for use in a JSON feed to our JS autocompletion functions. """ custom_permissions = permissions.GetCustomPermissions(project) choices = [] for action, perm, doc in freq_restrictions: choices.append({ 'name': 'Restrict-%s-%s' % (action, perm), 'doc': doc, }) for action in actions: for perm in custom_permissions: choices.append({ 'name': 'Restrict-%s-%s' % (action, perm), 'doc': 'Permission %s needed to use %s' % (perm, action), }) return choices
def GetCustomPermissions(self, mc, request): """Return the custom permissions for the given project.""" project = self._GetProject(mc, request) custom_permissions = permissions.GetCustomPermissions(project) result = projects_pb2.GetCustomPermissionsResponse( permissions=custom_permissions) return result
def GetLabelOptions(self, mc, request): """Return the label options for autocomplete for the given project.""" project = self._GetProject(mc, request) with work_env.WorkEnv(mc, self.services) as we: config = we.GetProjectConfig(project.project_id) label_options = tracker_helpers.GetLabelOptions( config, permissions.GetCustomPermissions(project)) label_defs = [ project_objects_pb2.LabelDef(label=label['name'], docstring=label['doc']) for label in label_options ] result = projects_pb2.GetLabelOptionsResponse( label_options=label_defs, exclusive_label_prefixes=config.exclusive_label_prefixes) return result
def HandleRequest(self, mr): """Provide the UI with info used in auto-completion. Args: mr: common information parsed from the HTTP request. Returns: Results dictionary in JSON format """ # Issue options data can be cached separately in each user's browser. When # the project changes, a new cached_content_timestamp is set and it will # cause new requests to use a new URL. self.SetCacheHeaders(self.response) member_data = project_helpers.BuildProjectMembers( mr.cnxn, mr.project, self.services.user) owner_views = member_data['owners'] committer_views = member_data['committers'] contributor_views = member_data['contributors'] config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) open_statuses = [] closed_statuses = [] for wks in config.well_known_statuses: if not wks.deprecated: item = dict(name=wks.status, doc=wks.status_docstring) if wks.means_open: open_statuses.append(item) else: closed_statuses.append(item) # TODO(jrobbins): restrictions on component definitions? components = [{'name': cd.path, 'doc': cd.docstring} for cd in config.component_defs if not cd.deprecated] labels = [] field_names = [ fd.field_name for fd in config.field_defs if not fd.is_deleted] non_masked_labels = tracker_helpers.LabelsNotMaskedByFields( config, field_names) for wkl in non_masked_labels: if not wkl.commented: item = dict(name=wkl.name, doc=wkl.docstring) labels.append(item) # TODO(jrobbins): omit fields that they don't have permission to view. field_def_views = [ tracker_views.FieldDefView(fd, config) for fd in config.field_defs if not fd.is_deleted] fields = [ dict(field_name=fdv.field_name, field_type=fdv.field_type, field_id=fdv.field_id, needs_perm=fdv.needs_perm, is_required=fdv.is_required, is_multivalued=fdv.is_multivalued, choices=[dict(name=c.name, doc=c.docstring) for c in fdv.choices], docstring=fdv.docstring) for fdv in field_def_views] frequent_restrictions = _FREQUENT_ISSUE_RESTRICTIONS[:] custom_permissions = permissions.GetCustomPermissions(mr.project) if not custom_permissions: frequent_restrictions.extend( _EXAMPLE_ISSUE_RESTRICTIONS) labels.extend(_BuildRestrictionChoices( mr.project, frequent_restrictions, permissions.STANDARD_ISSUE_PERMISSIONS)) group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, [mem.user_id for mem in member_data['all_members']]) logging.info('group_ids is %r', group_ids) acexclusion_ids = self.services.project.GetProjectAutocompleteExclusion( mr.cnxn, mr.project_id) # 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 = self.services.usergroup.LookupVisibleMembers( mr.cnxn, group_ids, mr.perms, mr.auth.effective_ids, self.services) indirect_ids = set() for gid in group_ids: indirect_ids.update(member_ids.get(gid, [])) indirect_ids.update(owner_ids.get(gid, [])) indirect_user_ids = list(indirect_ids) indirect_member_views = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, indirect_user_ids).values() visible_member_views = _FilterMemberData( mr, owner_views, committer_views, contributor_views, indirect_member_views) # Filter out servbice accounts visible_member_views = [m for m in visible_member_views if not framework_helpers.IsServiceAccount(m.email) and not m.user_id in acexclusion_ids] visible_member_email_list = list({ uv.email for uv in visible_member_views}) user_indexes = {email: idx for idx, email in enumerate(visible_member_email_list)} visible_members_dict = {} for uv in visible_member_views: visible_members_dict[uv.email] = uv.user_id group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, visible_members_dict.values()) for field_dict in fields: needed_perm = field_dict['needs_perm'] if needed_perm: qualified_user_indexes = [] for uv in visible_member_views: # TODO(jrobbins): Similar code occurs in field_helpers.py. user = self.services.user.GetUser(mr.cnxn, uv.user_id) auth = monorailrequest.AuthData.FromUserID( mr.cnxn, uv.user_id, self.services) user_perms = permissions.GetPermissions( user, auth.effective_ids, mr.project) has_perm = user_perms.CanUsePerm( needed_perm, auth.effective_ids, mr.project, []) if has_perm: qualified_user_indexes.append(user_indexes[uv.email]) field_dict['user_indexes'] = sorted(set(qualified_user_indexes)) excl_prefixes = [prefix.lower() for prefix in config.exclusive_label_prefixes] members_def_list = [dict(name=email, doc='') for email in visible_member_email_list] members_def_list = sorted( members_def_list, key=lambda md: md['name']) for md in members_def_list: md_id = visible_members_dict[md['name']] if md_id in group_ids: md['is_group'] = True return { 'open': open_statuses, 'closed': closed_statuses, 'statuses_offer_merge': config.statuses_offer_merge, 'components': components, 'labels': labels, 'fields': fields, 'excl_prefixes': excl_prefixes, 'strict': ezt.boolean(config.restrict_to_known), 'members': members_def_list, 'custom_permissions': custom_permissions, }