def test_combined_serializer(self): projects = [self.project, self.create_project()] alert_rule = self.create_alert_rule(projects=projects) issue_rule = self.create_issue_alert_rule( data={ "project": self.project, "name": "Issue Rule Test", "conditions": [], "actions": [], "actionMatch": "all", }) other_alert_rule = self.create_alert_rule() result = serialize([alert_rule, issue_rule, other_alert_rule], serializer=CombinedRuleSerializer()) self.assert_alert_rule_serialized(alert_rule, result[0]) assert result[1]["id"] == str(issue_rule.id) self.assert_alert_rule_serialized(other_alert_rule, result[2])
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) 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, )
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, )