def get(self, request, project): """ Fetches alert rules and legacy rules for a project """ alert_rules = AlertRule.objects.fetch_for_project(project) if not features.has("organizations:performance-view", project.organization): # Filter to only error alert rules alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value) alert_rule_intermediary = CombinedQuerysetIntermediary(alert_rules, "date_added") rule_intermediary = CombinedQuerysetIntermediary( Rule.objects.filter( project=project, status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE] ), "date_added", ) return self.paginate( request, paginator_cls=CombinedQuerysetPaginator, on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer()), default_per_page=25, intermediaries=[alert_rule_intermediary, rule_intermediary], desc=True, )
def get(self, request, organization): """ Fetches alert rules and legacy rules for an organization """ project_ids = self.get_requested_project_ids(request) or None alert_rules = AlertRule.objects.fetch_for_organization(organization, project_ids) if not features.has("organizations:performance-view", organization): # Filter to only error alert rules alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value) if project_ids is None: project_ids = Project.objects.filter(organization=organization).values_list( "id", flat=True ) issue_rules = Rule.objects.filter( status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=project_ids ) is_asc = request.GET.get("asc", False) sort_key = request.GET.get("sort", "date_added") rule_sort_key = ( sort_key if sort_key != "name" else "label" ) # Rule's don't share the same field name for their title/label/name...so we account for that here. alert_rule_intermediary = CombinedQuerysetIntermediary(alert_rules, sort_key) rule_intermediary = CombinedQuerysetIntermediary(issue_rules, rule_sort_key) return self.paginate( request, paginator_cls=CombinedQuerysetPaginator, on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer()), default_per_page=25, intermediaries=[alert_rule_intermediary, rule_intermediary], desc=not is_asc, )
def test_mix_date_and_not_date(self): with self.assertRaises(AssertionError): rule_intermediary = CombinedQuerysetIntermediary(Rule.objects.all(), "date_added") rule_intermediary2 = CombinedQuerysetIntermediary(Rule.objects.all(), "label") CombinedQuerysetPaginator( intermediaries=[rule_intermediary, rule_intermediary2], )
def get(self, request, organization): """ Fetches alert rules and legacy rules for an organization """ project_ids = self.get_requested_project_ids(request) or None if project_ids == {-1}: # All projects for org: project_ids = Project.objects.filter( organization=organization).values_list("id", flat=True) elif project_ids is None: # All projects for user org_team_list = Team.objects.filter( organization=organization).values_list("id", flat=True) user_team_list = OrganizationMemberTeam.objects.filter( organizationmember__user=request.user, team__in=org_team_list).values_list("team", flat=True) project_ids = Project.objects.filter( teams__in=user_team_list).values_list("id", flat=True) teams = set(request.GET.getlist("team", [])) team_filter_query = None if teams: # do normal teams lookup based on request params verified_ids = set() unassigned = None if "unassigned" in teams: teams.remove("unassigned") unassigned = Q(owner_id=None) if "myteams" in teams: teams.remove("myteams") if is_active_superuser(request): # retrieve all teams within the organization myteams = Team.objects.filter( organization=organization, status=TeamStatus.VISIBLE).values_list("id", flat=True) verified_ids.update(myteams) else: myteams = [t.id for t in request.access.teams] verified_ids.update(myteams) for team_id in teams: # Verify each passed Team id is numeric if type(team_id) is not int and not team_id.isdigit(): return Response(f"Invalid Team ID: {team_id}", status=status.HTTP_400_BAD_REQUEST) teams.update(verified_ids) teams = Team.objects.filter(id__in=teams) for team in teams: if team.id in verified_ids: continue if not request.access.has_team_access(team): return Response( f"Error: You do not have permission to access {team.name}", status=status.HTTP_400_BAD_REQUEST, ) team_filter_query = Q( owner_id__in=teams.values_list("actor_id", flat=True)) if unassigned: team_filter_query = team_filter_query | unassigned alert_rules = AlertRule.objects.fetch_for_organization( organization, project_ids) if not features.has("organizations:performance-view", organization): # Filter to only error alert rules alert_rules = alert_rules.filter( snuba_query__dataset=Dataset.Events.value) issue_rules = Rule.objects.filter( status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=project_ids) name = request.GET.get("name", None) if name: alert_rules = alert_rules.filter(Q(name__icontains=name)) issue_rules = issue_rules.filter(Q(label__icontains=name)) if team_filter_query: alert_rules = alert_rules.filter(team_filter_query) issue_rules = issue_rules.filter(team_filter_query) is_asc = request.GET.get("asc", False) == "1" sort_key = request.GET.get("sort", "date_added") rule_sort_key = ( sort_key if sort_key != "name" else "label" ) # Rule's don't share the same field name for their title/label/name...so we account for that here. case_insensitive = sort_key == "name" alert_rule_intermediary = CombinedQuerysetIntermediary( alert_rules, sort_key) rule_intermediary = CombinedQuerysetIntermediary( issue_rules, rule_sort_key) return self.paginate( request, paginator_cls=CombinedQuerysetPaginator, on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer()), default_per_page=25, intermediaries=[alert_rule_intermediary, rule_intermediary], desc=not is_asc, cursor_cls=StringCursor if case_insensitive else Cursor, case_insensitive=case_insensitive, )
def test_order_by_invalid_key(self): with self.assertRaises(AssertionError): rule_intermediary = CombinedQuerysetIntermediary( Rule.objects.all(), "dontexist") CombinedQuerysetPaginator(intermediaries=[rule_intermediary], )
def test_simple(self): Rule.objects.all().delete() alert_rule0 = self.create_alert_rule(name="alertrule0") alert_rule1 = self.create_alert_rule(name="alertrule1") rule1 = Rule.objects.create(label="rule1", project=self.project) alert_rule2 = self.create_alert_rule(name="alertrule2") alert_rule3 = self.create_alert_rule(name="alertrule3") rule2 = Rule.objects.create(label="rule2", project=self.project) rule3 = Rule.objects.create(label="rule3", project=self.project) alert_rule_intermediary = CombinedQuerysetIntermediary( AlertRule.objects.all(), "date_added") rule_intermediary = CombinedQuerysetIntermediary( Rule.objects.all(), "date_added") paginator = CombinedQuerysetPaginator( intermediaries=[alert_rule_intermediary, rule_intermediary], desc=True, ) result = paginator.get_result(limit=3, cursor=None) assert len(result) == 3 page1_results = list(result) assert page1_results[0].id == rule3.id assert page1_results[1].id == rule2.id assert page1_results[2].id == alert_rule3.id next_cursor = result.next result = paginator.get_result(limit=3, cursor=next_cursor) page2_results = list(result) assert len(result) == 3 assert page2_results[0].id == alert_rule2.id assert page2_results[1].id == rule1.id assert page2_results[2].id == alert_rule1.id next_cursor = result.next prev_cursor = result.prev result = paginator.get_result(limit=3, cursor=next_cursor) page3_results = list(result) assert len(result) == 2 assert page3_results[0].id == alert_rule0.id result = paginator.get_result(limit=3, cursor=prev_cursor) assert list(result) == page1_results # Test reverse sorting: paginator = CombinedQuerysetPaginator( intermediaries=[alert_rule_intermediary, rule_intermediary], ) result = paginator.get_result(limit=3, cursor=None) assert len(result) == 3 page1_results = list(result) assert page1_results[0].id == Rule.objects.all().first().id assert page1_results[1].id == alert_rule0.id assert page1_results[2].id == alert_rule1.id next_cursor = result.next result = paginator.get_result(limit=3, cursor=next_cursor) page2_results = list(result) assert len(result) == 3 assert page2_results[0].id == rule1.id assert page2_results[1].id == alert_rule2.id assert page2_results[2].id == alert_rule3.id next_cursor = result.next prev_cursor = result.prev result = paginator.get_result(limit=3, cursor=next_cursor) page3_results = list(result) assert len(result) == 2 assert page3_results[0].id == rule2.id assert page3_results[1].id == rule3.id result = paginator.get_result(limit=3, cursor=prev_cursor) assert list(result) == page1_results
def get(self, request, organization): """ Fetches alert rules and legacy rules for an organization """ project_ids = self.get_requested_project_ids(request) or None if project_ids == {-1}: # All projects for org: project_ids = Project.objects.filter( organization=organization).values_list("id", flat=True) elif project_ids is None: # All projects for user org_team_list = Team.objects.filter( organization=organization).values_list("id", flat=True) user_team_list = OrganizationMemberTeam.objects.filter( organizationmember__user=request.user, team__in=org_team_list).values_list("team", flat=True) project_ids = Project.objects.filter( teams__in=user_team_list).values_list("id", flat=True) teams = request.GET.getlist("team", []) team_filter_query = None if len(teams) > 0: try: teams_query, unassigned = parse_team_params( request, organization, teams) except InvalidParams as err: return Response(str(err), status=status.HTTP_400_BAD_REQUEST) team_filter_query = Q( owner_id__in=teams_query.values_list("actor_id", flat=True)) if unassigned: team_filter_query = team_filter_query | Q(owner_id=None) alert_rules = AlertRule.objects.fetch_for_organization( organization, project_ids) if not features.has("organizations:performance-view", organization): # Filter to only error alert rules alert_rules = alert_rules.filter( snuba_query__dataset=Dataset.Events.value) issue_rules = Rule.objects.filter( status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=project_ids) name = request.GET.get("name", None) if name: alert_rules = alert_rules.filter(Q(name__icontains=name)) issue_rules = issue_rules.filter(Q(label__icontains=name)) if team_filter_query: alert_rules = alert_rules.filter(team_filter_query) issue_rules = issue_rules.filter(team_filter_query) expand = request.GET.getlist("expand", []) if "latestIncident" in expand: alert_rules = alert_rules.annotate(incident_id=Coalesce( Subquery( Incident.objects.filter(alert_rule=OuterRef( "pk")).order_by("-date_started").values("id")[:1]), Value("-1"), )) is_asc = request.GET.get("asc", False) == "1" sort_key = request.GET.getlist("sort", ["date_added"]) rule_sort_key = [ "label" if x == "name" else x for x in sort_key ] # Rule's don't share the same field name for their title/label/name...so we account for that here. case_insensitive = sort_key == ["name"] if "incident_status" in sort_key: alert_rules = alert_rules.annotate(incident_status=Coalesce( Subquery( Incident.objects.filter(alert_rule=OuterRef( "pk")).order_by("-date_started").values("status")[:1]), Value(-1, output_field=IntegerField()), )) issue_rules = issue_rules.annotate( incident_status=Value(-2, output_field=IntegerField())) if "date_triggered" in sort_key: far_past_date = Value(datetime.min, output_field=DateTimeField()) alert_rules = alert_rules.annotate(date_triggered=Coalesce( Subquery( Incident.objects.filter(alert_rule=OuterRef("pk")). order_by("-date_started").values("date_started")[:1]), far_past_date, ), ) issue_rules = issue_rules.annotate(date_triggered=far_past_date) alert_rule_intermediary = CombinedQuerysetIntermediary( alert_rules, sort_key) rule_intermediary = CombinedQuerysetIntermediary( issue_rules, rule_sort_key) return self.paginate( request, paginator_cls=CombinedQuerysetPaginator, on_results=lambda x: serialize( x, request.user, CombinedRuleSerializer(expand=expand)), default_per_page=25, intermediaries=[alert_rule_intermediary, rule_intermediary], desc=not is_asc, cursor_cls=StringCursor if case_insensitive else Cursor, case_insensitive=case_insensitive, )