We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Alert Page broken after delete project 
### Self-Hosted Version

22.8.0

### CPU Architecture

x86_64

### Docker Version

20.10.17, build 100c701

### Docker Compose Version

2.6.0

### Steps to Reproduce

1. create project
2. set a alert rule for it
3. delete this project

### Expected Result

Alert will be deleted too.

### Actual Result

Alert Page broken after delete project.
Returns 403, detail is you don't have permission.
Manually fixed by:
```
\dt
select * from sentry_alertrule;
select * from sentry_alertruleactivity;
select * from sentry_alertruleexcludedprojects;
select * from sentry_alertruletrigger;
select * from sentry_alertruletriggeraction;
select * from sentry_alertruletriggerexclusion;
\dt
select * from sentry_rule;
delete from sentry_rule where id = 2;
select * from sentry_grouprulestatus;
delete from sentry_grouprulestatus where rule_id = 2;
delete from sentry_rule where id = 2;
select * from sentry_ruleactivity;
delete from sentry_ruleactivity where rule_id = 2;
delete from sentry_rule where id = 2;
delete from sentry_rulefirehistory where rule_id = 2;
delete from sentry_rule where id = 2;
select * from sentry_rule;
\dt
select * from sentry_userrole;
select * from sentry_userpermission;
select * from sentry_userrole_users;
select * from sentry_ruleactivity;
select * from sentry_rule;
select * from sentry_ruleactivity_id_seq;
select * from sentry_rulefirehistory;
select * from sentry_rulefirehistory_id_seq;
select * from sentry_rule_id_seq;
\q

```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/sentry/incidents/endpoints/organization_alert_rule_index.py`
Content:
```
1 from datetime import datetime
2 
3 from django.db.models import DateTimeField, IntegerField, OuterRef, Q, Subquery, Value
4 from django.db.models.functions import Coalesce
5 from django.utils.timezone import make_aware
6 from rest_framework import status
7 from rest_framework.request import Request
8 from rest_framework.response import Response
9 
10 from sentry import features
11 from sentry.api.base import region_silo_endpoint
12 from sentry.api.bases.organization import OrganizationAlertRulePermission, OrganizationEndpoint
13 from sentry.api.exceptions import ResourceDoesNotExist
14 from sentry.api.paginator import (
15     CombinedQuerysetIntermediary,
16     CombinedQuerysetPaginator,
17     OffsetPaginator,
18 )
19 from sentry.api.serializers import serialize
20 from sentry.api.serializers.models.alert_rule import CombinedRuleSerializer
21 from sentry.api.utils import InvalidParams
22 from sentry.incidents.models import AlertRule, Incident
23 from sentry.incidents.serializers import AlertRuleSerializer
24 from sentry.models import OrganizationMemberTeam, Project, ProjectStatus, Rule, RuleStatus, Team
25 from sentry.snuba.dataset import Dataset
26 from sentry.utils.cursors import Cursor, StringCursor
27 
28 from .utils import parse_team_params
29 
30 
31 @region_silo_endpoint
32 class OrganizationCombinedRuleIndexEndpoint(OrganizationEndpoint):
33     def get(self, request: Request, organization) -> Response:
34         """
35         Fetches alert rules and legacy rules for an organization
36         """
37         project_ids = self.get_requested_project_ids_unchecked(request) or None
38         if project_ids == {-1}:  # All projects for org:
39             project_ids = Project.objects.filter(
40                 organization=organization, status=ProjectStatus.VISIBLE
41             ).values_list("id", flat=True)
42         elif project_ids is None:  # All projects for user
43             org_team_list = Team.objects.filter(organization=organization).values_list(
44                 "id", flat=True
45             )
46             user_team_list = OrganizationMemberTeam.objects.filter(
47                 organizationmember__user=request.user, team__in=org_team_list
48             ).values_list("team", flat=True)
49             project_ids = Project.objects.filter(teams__in=user_team_list).values_list(
50                 "id", flat=True
51             )
52 
53         # Materialize the project ids here. This helps us to not overwhelm the query planner with
54         # overcomplicated subqueries. Previously, this was causing Postgres to use a suboptimal
55         # index to filter on. Also enforces permission checks.
56         projects = self.get_projects(request, organization, project_ids=set(project_ids))
57 
58         teams = request.GET.getlist("team", [])
59         team_filter_query = None
60         if len(teams) > 0:
61             try:
62                 teams_query, unassigned = parse_team_params(request, organization, teams)
63             except InvalidParams as err:
64                 return Response(str(err), status=status.HTTP_400_BAD_REQUEST)
65 
66             team_filter_query = Q(owner_id__in=teams_query.values_list("actor_id", flat=True))
67             if unassigned:
68                 team_filter_query = team_filter_query | Q(owner_id=None)
69 
70         alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)
71         if not features.has("organizations:performance-view", organization):
72             # Filter to only error alert rules
73             alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)
74         issue_rules = Rule.objects.filter(
75             status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=projects
76         )
77         name = request.GET.get("name", None)
78         if name:
79             alert_rules = alert_rules.filter(Q(name__icontains=name))
80             issue_rules = issue_rules.filter(Q(label__icontains=name))
81 
82         if team_filter_query:
83             alert_rules = alert_rules.filter(team_filter_query)
84             issue_rules = issue_rules.filter(team_filter_query)
85 
86         expand = request.GET.getlist("expand", [])
87         if "latestIncident" in expand:
88             alert_rules = alert_rules.annotate(
89                 incident_id=Coalesce(
90                     Subquery(
91                         Incident.objects.filter(alert_rule=OuterRef("pk"))
92                         .order_by("-date_started")
93                         .values("id")[:1]
94                     ),
95                     Value("-1"),
96                 )
97             )
98 
99         is_asc = request.GET.get("asc", False) == "1"
100         sort_key = request.GET.getlist("sort", ["date_added"])
101         rule_sort_key = [
102             "label" if x == "name" else x for x in sort_key
103         ]  # Rule's don't share the same field name for their title/label/name...so we account for that here.
104         case_insensitive = sort_key == ["name"]
105 
106         if "incident_status" in sort_key:
107             alert_rules = alert_rules.annotate(
108                 incident_status=Coalesce(
109                     Subquery(
110                         Incident.objects.filter(alert_rule=OuterRef("pk"))
111                         .order_by("-date_started")
112                         .values("status")[:1]
113                     ),
114                     Value(-1, output_field=IntegerField()),
115                 )
116             )
117             issue_rules = issue_rules.annotate(
118                 incident_status=Value(-2, output_field=IntegerField())
119             )
120 
121         if "date_triggered" in sort_key:
122             far_past_date = Value(make_aware(datetime.min), output_field=DateTimeField())
123             alert_rules = alert_rules.annotate(
124                 date_triggered=Coalesce(
125                     Subquery(
126                         Incident.objects.filter(alert_rule=OuterRef("pk"))
127                         .order_by("-date_started")
128                         .values("date_started")[:1]
129                     ),
130                     far_past_date,
131                 ),
132             )
133             issue_rules = issue_rules.annotate(date_triggered=far_past_date)
134         alert_rules_count = alert_rules.count()
135         issue_rules_count = issue_rules.count()
136         alert_rule_intermediary = CombinedQuerysetIntermediary(alert_rules, sort_key)
137         rule_intermediary = CombinedQuerysetIntermediary(issue_rules, rule_sort_key)
138         response = self.paginate(
139             request,
140             paginator_cls=CombinedQuerysetPaginator,
141             on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer(expand=expand)),
142             default_per_page=25,
143             intermediaries=[alert_rule_intermediary, rule_intermediary],
144             desc=not is_asc,
145             cursor_cls=StringCursor if case_insensitive else Cursor,
146             case_insensitive=case_insensitive,
147         )
148         response["X-Sentry-Issue-Rule-Hits"] = issue_rules_count
149         response["X-Sentry-Alert-Rule-Hits"] = alert_rules_count
150         return response
151 
152 
153 @region_silo_endpoint
154 class OrganizationAlertRuleIndexEndpoint(OrganizationEndpoint):
155     permission_classes = (OrganizationAlertRulePermission,)
156 
157     def get(self, request: Request, organization) -> Response:
158         """
159         Fetches alert rules for an organization
160         """
161         if not features.has("organizations:incidents", organization, actor=request.user):
162             raise ResourceDoesNotExist
163 
164         projects = self.get_projects(request, organization)
165         alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)
166         if not features.has("organizations:performance-view", organization):
167             # Filter to only error alert rules
168             alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)
169 
170         return self.paginate(
171             request,
172             queryset=alert_rules,
173             order_by="-date_added",
174             paginator_cls=OffsetPaginator,
175             on_results=lambda x: serialize(x, request.user),
176             default_per_page=25,
177         )
178 
179     def post(self, request: Request, organization) -> Response:
180         """
181         Create an alert rule
182         """
183 
184         if not features.has("organizations:incidents", organization, actor=request.user):
185             raise ResourceDoesNotExist
186 
187         serializer = AlertRuleSerializer(
188             context={"organization": organization, "access": request.access, "user": request.user},
189             data=request.data,
190         )
191 
192         if serializer.is_valid():
193             alert_rule = serializer.save()
194             return Response(serialize(alert_rule, request.user), status=status.HTTP_201_CREATED)
195 
196         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
197
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/sentry/incidents/endpoints/organization_alert_rule_index.py b/src/sentry/incidents/endpoints/organization_alert_rule_index.py
--- a/src/sentry/incidents/endpoints/organization_alert_rule_index.py
+++ b/src/sentry/incidents/endpoints/organization_alert_rule_index.py
@@ -46,9 +46,9 @@
             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
-            )
+            project_ids = Project.objects.filter(
+                teams__in=user_team_list, status=ProjectStatus.VISIBLE
+            ).values_list("id", flat=True)
 
         # Materialize the project ids here. This helps us to not overwhelm the query planner with
         # overcomplicated subqueries. Previously, this was causing Postgres to use a suboptimal

{"golden_diff": "diff --git a/src/sentry/incidents/endpoints/organization_alert_rule_index.py b/src/sentry/incidents/endpoints/organization_alert_rule_index.py\n--- a/src/sentry/incidents/endpoints/organization_alert_rule_index.py\n+++ b/src/sentry/incidents/endpoints/organization_alert_rule_index.py\n@@ -46,9 +46,9 @@\n             user_team_list = OrganizationMemberTeam.objects.filter(\n                 organizationmember__user=request.user, team__in=org_team_list\n             ).values_list(\"team\", flat=True)\n-            project_ids = Project.objects.filter(teams__in=user_team_list).values_list(\n-                \"id\", flat=True\n-            )\n+            project_ids = Project.objects.filter(\n+                teams__in=user_team_list, status=ProjectStatus.VISIBLE\n+            ).values_list(\"id\", flat=True)\n \n         # Materialize the project ids here. This helps us to not overwhelm the query planner with\n         # overcomplicated subqueries. Previously, this was causing Postgres to use a suboptimal\n", "issue": "Alert Page broken after delete project \n### Self-Hosted Version\n\n22.8.0\n\n### CPU Architecture\n\nx86_64\n\n### Docker Version\n\n20.10.17, build 100c701\n\n### Docker Compose Version\n\n2.6.0\n\n### Steps to Reproduce\n\n1. create project\r\n2. set a alert rule for it\r\n3. delete this project\n\n### Expected Result\n\nAlert will be deleted too.\n\n### Actual Result\n\nAlert Page broken after delete project.\r\nReturns 403, detail is you don't have permission.\r\nManually fixed by:\r\n```\r\n\\dt\r\nselect * from sentry_alertrule;\r\nselect * from sentry_alertruleactivity;\r\nselect * from sentry_alertruleexcludedprojects;\r\nselect * from sentry_alertruletrigger;\r\nselect * from sentry_alertruletriggeraction;\r\nselect * from sentry_alertruletriggerexclusion;\r\n\\dt\r\nselect * from sentry_rule;\r\ndelete from sentry_rule where id = 2;\r\nselect * from sentry_grouprulestatus;\r\ndelete from sentry_grouprulestatus where rule_id = 2;\r\ndelete from sentry_rule where id = 2;\r\nselect * from sentry_ruleactivity;\r\ndelete from sentry_ruleactivity where rule_id = 2;\r\ndelete from sentry_rule where id = 2;\r\ndelete from sentry_rulefirehistory where rule_id = 2;\r\ndelete from sentry_rule where id = 2;\r\nselect * from sentry_rule;\r\n\\dt\r\nselect * from sentry_userrole;\r\nselect * from sentry_userpermission;\r\nselect * from sentry_userrole_users;\r\nselect * from sentry_ruleactivity;\r\nselect * from sentry_rule;\r\nselect * from sentry_ruleactivity_id_seq;\r\nselect * from sentry_rulefirehistory;\r\nselect * from sentry_rulefirehistory_id_seq;\r\nselect * from sentry_rule_id_seq;\r\n\\q\r\n\r\n```\n", "before_files": [{"content": "from datetime import datetime\n\nfrom django.db.models import DateTimeField, IntegerField, OuterRef, Q, Subquery, Value\nfrom django.db.models.functions import Coalesce\nfrom django.utils.timezone import make_aware\nfrom rest_framework import status\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\n\nfrom sentry import features\nfrom sentry.api.base import region_silo_endpoint\nfrom sentry.api.bases.organization import OrganizationAlertRulePermission, OrganizationEndpoint\nfrom sentry.api.exceptions import ResourceDoesNotExist\nfrom sentry.api.paginator import (\n    CombinedQuerysetIntermediary,\n    CombinedQuerysetPaginator,\n    OffsetPaginator,\n)\nfrom sentry.api.serializers import serialize\nfrom sentry.api.serializers.models.alert_rule import CombinedRuleSerializer\nfrom sentry.api.utils import InvalidParams\nfrom sentry.incidents.models import AlertRule, Incident\nfrom sentry.incidents.serializers import AlertRuleSerializer\nfrom sentry.models import OrganizationMemberTeam, Project, ProjectStatus, Rule, RuleStatus, Team\nfrom sentry.snuba.dataset import Dataset\nfrom sentry.utils.cursors import Cursor, StringCursor\n\nfrom .utils import parse_team_params\n\n\n@region_silo_endpoint\nclass OrganizationCombinedRuleIndexEndpoint(OrganizationEndpoint):\n    def get(self, request: Request, organization) -> Response:\n        \"\"\"\n        Fetches alert rules and legacy rules for an organization\n        \"\"\"\n        project_ids = self.get_requested_project_ids_unchecked(request) or None\n        if project_ids == {-1}:  # All projects for org:\n            project_ids = Project.objects.filter(\n                organization=organization, status=ProjectStatus.VISIBLE\n            ).values_list(\"id\", flat=True)\n        elif project_ids is None:  # All projects for user\n            org_team_list = Team.objects.filter(organization=organization).values_list(\n                \"id\", flat=True\n            )\n            user_team_list = OrganizationMemberTeam.objects.filter(\n                organizationmember__user=request.user, team__in=org_team_list\n            ).values_list(\"team\", flat=True)\n            project_ids = Project.objects.filter(teams__in=user_team_list).values_list(\n                \"id\", flat=True\n            )\n\n        # Materialize the project ids here. This helps us to not overwhelm the query planner with\n        # overcomplicated subqueries. Previously, this was causing Postgres to use a suboptimal\n        # index to filter on. Also enforces permission checks.\n        projects = self.get_projects(request, organization, project_ids=set(project_ids))\n\n        teams = request.GET.getlist(\"team\", [])\n        team_filter_query = None\n        if len(teams) > 0:\n            try:\n                teams_query, unassigned = parse_team_params(request, organization, teams)\n            except InvalidParams as err:\n                return Response(str(err), status=status.HTTP_400_BAD_REQUEST)\n\n            team_filter_query = Q(owner_id__in=teams_query.values_list(\"actor_id\", flat=True))\n            if unassigned:\n                team_filter_query = team_filter_query | Q(owner_id=None)\n\n        alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)\n        if not features.has(\"organizations:performance-view\", organization):\n            # Filter to only error alert rules\n            alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)\n        issue_rules = Rule.objects.filter(\n            status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=projects\n        )\n        name = request.GET.get(\"name\", None)\n        if name:\n            alert_rules = alert_rules.filter(Q(name__icontains=name))\n            issue_rules = issue_rules.filter(Q(label__icontains=name))\n\n        if team_filter_query:\n            alert_rules = alert_rules.filter(team_filter_query)\n            issue_rules = issue_rules.filter(team_filter_query)\n\n        expand = request.GET.getlist(\"expand\", [])\n        if \"latestIncident\" in expand:\n            alert_rules = alert_rules.annotate(\n                incident_id=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"id\")[:1]\n                    ),\n                    Value(\"-1\"),\n                )\n            )\n\n        is_asc = request.GET.get(\"asc\", False) == \"1\"\n        sort_key = request.GET.getlist(\"sort\", [\"date_added\"])\n        rule_sort_key = [\n            \"label\" if x == \"name\" else x for x in sort_key\n        ]  # Rule's don't share the same field name for their title/label/name...so we account for that here.\n        case_insensitive = sort_key == [\"name\"]\n\n        if \"incident_status\" in sort_key:\n            alert_rules = alert_rules.annotate(\n                incident_status=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"status\")[:1]\n                    ),\n                    Value(-1, output_field=IntegerField()),\n                )\n            )\n            issue_rules = issue_rules.annotate(\n                incident_status=Value(-2, output_field=IntegerField())\n            )\n\n        if \"date_triggered\" in sort_key:\n            far_past_date = Value(make_aware(datetime.min), output_field=DateTimeField())\n            alert_rules = alert_rules.annotate(\n                date_triggered=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"date_started\")[:1]\n                    ),\n                    far_past_date,\n                ),\n            )\n            issue_rules = issue_rules.annotate(date_triggered=far_past_date)\n        alert_rules_count = alert_rules.count()\n        issue_rules_count = issue_rules.count()\n        alert_rule_intermediary = CombinedQuerysetIntermediary(alert_rules, sort_key)\n        rule_intermediary = CombinedQuerysetIntermediary(issue_rules, rule_sort_key)\n        response = self.paginate(\n            request,\n            paginator_cls=CombinedQuerysetPaginator,\n            on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer(expand=expand)),\n            default_per_page=25,\n            intermediaries=[alert_rule_intermediary, rule_intermediary],\n            desc=not is_asc,\n            cursor_cls=StringCursor if case_insensitive else Cursor,\n            case_insensitive=case_insensitive,\n        )\n        response[\"X-Sentry-Issue-Rule-Hits\"] = issue_rules_count\n        response[\"X-Sentry-Alert-Rule-Hits\"] = alert_rules_count\n        return response\n\n\n@region_silo_endpoint\nclass OrganizationAlertRuleIndexEndpoint(OrganizationEndpoint):\n    permission_classes = (OrganizationAlertRulePermission,)\n\n    def get(self, request: Request, organization) -> Response:\n        \"\"\"\n        Fetches alert rules for an organization\n        \"\"\"\n        if not features.has(\"organizations:incidents\", organization, actor=request.user):\n            raise ResourceDoesNotExist\n\n        projects = self.get_projects(request, organization)\n        alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)\n        if not features.has(\"organizations:performance-view\", organization):\n            # Filter to only error alert rules\n            alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)\n\n        return self.paginate(\n            request,\n            queryset=alert_rules,\n            order_by=\"-date_added\",\n            paginator_cls=OffsetPaginator,\n            on_results=lambda x: serialize(x, request.user),\n            default_per_page=25,\n        )\n\n    def post(self, request: Request, organization) -> Response:\n        \"\"\"\n        Create an alert rule\n        \"\"\"\n\n        if not features.has(\"organizations:incidents\", organization, actor=request.user):\n            raise ResourceDoesNotExist\n\n        serializer = AlertRuleSerializer(\n            context={\"organization\": organization, \"access\": request.access, \"user\": request.user},\n            data=request.data,\n        )\n\n        if serializer.is_valid():\n            alert_rule = serializer.save()\n            return Response(serialize(alert_rule, request.user), status=status.HTTP_201_CREATED)\n\n        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n", "path": "src/sentry/incidents/endpoints/organization_alert_rule_index.py"}], "after_files": [{"content": "from datetime import datetime\n\nfrom django.db.models import DateTimeField, IntegerField, OuterRef, Q, Subquery, Value\nfrom django.db.models.functions import Coalesce\nfrom django.utils.timezone import make_aware\nfrom rest_framework import status\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\n\nfrom sentry import features\nfrom sentry.api.base import region_silo_endpoint\nfrom sentry.api.bases.organization import OrganizationAlertRulePermission, OrganizationEndpoint\nfrom sentry.api.exceptions import ResourceDoesNotExist\nfrom sentry.api.paginator import (\n    CombinedQuerysetIntermediary,\n    CombinedQuerysetPaginator,\n    OffsetPaginator,\n)\nfrom sentry.api.serializers import serialize\nfrom sentry.api.serializers.models.alert_rule import CombinedRuleSerializer\nfrom sentry.api.utils import InvalidParams\nfrom sentry.incidents.models import AlertRule, Incident\nfrom sentry.incidents.serializers import AlertRuleSerializer\nfrom sentry.models import OrganizationMemberTeam, Project, ProjectStatus, Rule, RuleStatus, Team\nfrom sentry.snuba.dataset import Dataset\nfrom sentry.utils.cursors import Cursor, StringCursor\n\nfrom .utils import parse_team_params\n\n\n@region_silo_endpoint\nclass OrganizationCombinedRuleIndexEndpoint(OrganizationEndpoint):\n    def get(self, request: Request, organization) -> Response:\n        \"\"\"\n        Fetches alert rules and legacy rules for an organization\n        \"\"\"\n        project_ids = self.get_requested_project_ids_unchecked(request) or None\n        if project_ids == {-1}:  # All projects for org:\n            project_ids = Project.objects.filter(\n                organization=organization, status=ProjectStatus.VISIBLE\n            ).values_list(\"id\", flat=True)\n        elif project_ids is None:  # All projects for user\n            org_team_list = Team.objects.filter(organization=organization).values_list(\n                \"id\", flat=True\n            )\n            user_team_list = OrganizationMemberTeam.objects.filter(\n                organizationmember__user=request.user, team__in=org_team_list\n            ).values_list(\"team\", flat=True)\n            project_ids = Project.objects.filter(\n                teams__in=user_team_list, status=ProjectStatus.VISIBLE\n            ).values_list(\"id\", flat=True)\n\n        # Materialize the project ids here. This helps us to not overwhelm the query planner with\n        # overcomplicated subqueries. Previously, this was causing Postgres to use a suboptimal\n        # index to filter on. Also enforces permission checks.\n        projects = self.get_projects(request, organization, project_ids=set(project_ids))\n\n        teams = request.GET.getlist(\"team\", [])\n        team_filter_query = None\n        if len(teams) > 0:\n            try:\n                teams_query, unassigned = parse_team_params(request, organization, teams)\n            except InvalidParams as err:\n                return Response(str(err), status=status.HTTP_400_BAD_REQUEST)\n\n            team_filter_query = Q(owner_id__in=teams_query.values_list(\"actor_id\", flat=True))\n            if unassigned:\n                team_filter_query = team_filter_query | Q(owner_id=None)\n\n        alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)\n        if not features.has(\"organizations:performance-view\", organization):\n            # Filter to only error alert rules\n            alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)\n        issue_rules = Rule.objects.filter(\n            status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], project__in=projects\n        )\n        name = request.GET.get(\"name\", None)\n        if name:\n            alert_rules = alert_rules.filter(Q(name__icontains=name))\n            issue_rules = issue_rules.filter(Q(label__icontains=name))\n\n        if team_filter_query:\n            alert_rules = alert_rules.filter(team_filter_query)\n            issue_rules = issue_rules.filter(team_filter_query)\n\n        expand = request.GET.getlist(\"expand\", [])\n        if \"latestIncident\" in expand:\n            alert_rules = alert_rules.annotate(\n                incident_id=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"id\")[:1]\n                    ),\n                    Value(\"-1\"),\n                )\n            )\n\n        is_asc = request.GET.get(\"asc\", False) == \"1\"\n        sort_key = request.GET.getlist(\"sort\", [\"date_added\"])\n        rule_sort_key = [\n            \"label\" if x == \"name\" else x for x in sort_key\n        ]  # Rule's don't share the same field name for their title/label/name...so we account for that here.\n        case_insensitive = sort_key == [\"name\"]\n\n        if \"incident_status\" in sort_key:\n            alert_rules = alert_rules.annotate(\n                incident_status=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"status\")[:1]\n                    ),\n                    Value(-1, output_field=IntegerField()),\n                )\n            )\n            issue_rules = issue_rules.annotate(\n                incident_status=Value(-2, output_field=IntegerField())\n            )\n\n        if \"date_triggered\" in sort_key:\n            far_past_date = Value(make_aware(datetime.min), output_field=DateTimeField())\n            alert_rules = alert_rules.annotate(\n                date_triggered=Coalesce(\n                    Subquery(\n                        Incident.objects.filter(alert_rule=OuterRef(\"pk\"))\n                        .order_by(\"-date_started\")\n                        .values(\"date_started\")[:1]\n                    ),\n                    far_past_date,\n                ),\n            )\n            issue_rules = issue_rules.annotate(date_triggered=far_past_date)\n        alert_rules_count = alert_rules.count()\n        issue_rules_count = issue_rules.count()\n        alert_rule_intermediary = CombinedQuerysetIntermediary(alert_rules, sort_key)\n        rule_intermediary = CombinedQuerysetIntermediary(issue_rules, rule_sort_key)\n        response = self.paginate(\n            request,\n            paginator_cls=CombinedQuerysetPaginator,\n            on_results=lambda x: serialize(x, request.user, CombinedRuleSerializer(expand=expand)),\n            default_per_page=25,\n            intermediaries=[alert_rule_intermediary, rule_intermediary],\n            desc=not is_asc,\n            cursor_cls=StringCursor if case_insensitive else Cursor,\n            case_insensitive=case_insensitive,\n        )\n        response[\"X-Sentry-Issue-Rule-Hits\"] = issue_rules_count\n        response[\"X-Sentry-Alert-Rule-Hits\"] = alert_rules_count\n        return response\n\n\n@region_silo_endpoint\nclass OrganizationAlertRuleIndexEndpoint(OrganizationEndpoint):\n    permission_classes = (OrganizationAlertRulePermission,)\n\n    def get(self, request: Request, organization) -> Response:\n        \"\"\"\n        Fetches alert rules for an organization\n        \"\"\"\n        if not features.has(\"organizations:incidents\", organization, actor=request.user):\n            raise ResourceDoesNotExist\n\n        projects = self.get_projects(request, organization)\n        alert_rules = AlertRule.objects.fetch_for_organization(organization, projects)\n        if not features.has(\"organizations:performance-view\", organization):\n            # Filter to only error alert rules\n            alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value)\n\n        return self.paginate(\n            request,\n            queryset=alert_rules,\n            order_by=\"-date_added\",\n            paginator_cls=OffsetPaginator,\n            on_results=lambda x: serialize(x, request.user),\n            default_per_page=25,\n        )\n\n    def post(self, request: Request, organization) -> Response:\n        \"\"\"\n        Create an alert rule\n        \"\"\"\n\n        if not features.has(\"organizations:incidents\", organization, actor=request.user):\n            raise ResourceDoesNotExist\n\n        serializer = AlertRuleSerializer(\n            context={\"organization\": organization, \"access\": request.access, \"user\": request.user},\n            data=request.data,\n        )\n\n        if serializer.is_valid():\n            alert_rule = serializer.save()\n            return Response(serialize(alert_rule, request.user), status=status.HTTP_201_CREATED)\n\n        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n", "path": "src/sentry/incidents/endpoints/organization_alert_rule_index.py"}]}