Esempio n. 1
0
    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,
        )
Esempio n. 2
0
    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,
        )
Esempio n. 3
0
 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],
         )
Esempio n. 4
0
    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,
        )
Esempio n. 5
0
 def test_order_by_invalid_key(self):
     with self.assertRaises(AssertionError):
         rule_intermediary = CombinedQuerysetIntermediary(
             Rule.objects.all(), "dontexist")
         CombinedQuerysetPaginator(intermediaries=[rule_intermediary], )
Esempio n. 6
0
    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,
        )