Repository: getsentry/sentry

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

```


Discussion:
Thanks for reporting this issue! I was able to successfully reproduce this issue both in a self-hosted setup locally and on sentry.io. Rerouting this issue to another team.
Routing to @getsentry/app-frontend for [triage](https://develop.sentry.dev/processing-tickets/#3-triage). ⏲️

Thanks for reporting this, I've added it to the workflow backlog.

Resolving patch:
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 @@ def get(self, request: Request, organization) -> Response:
             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


Test patch:
diff --git a/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py b/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py
--- a/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py
+++ b/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py
@@ -1184,3 +1184,21 @@ def test_last_triggered(self):
         RuleFireHistory.objects.create(project=self.project, rule=rule, group=self.group)
         resp = self.get_success_response(self.organization.slug, expand=["lastTriggered"])
         assert resp.data[0]["lastTriggered"] == datetime.now().replace(tzinfo=pytz.UTC)
+
+    def test_project_deleted(self):
+        from sentry.models import ScheduledDeletion
+        from sentry.tasks.deletion.scheduled import run_deletion
+
+        org = self.create_organization(owner=self.user, name="Rowdy Tiger")
+        team = self.create_team(organization=org, name="Mariachi Band", members=[self.user])
+        delete_project = self.create_project(organization=org, teams=[team], name="Bengal")
+        self.login_as(self.user)
+        self.create_project_rule(project=delete_project)
+
+        deletion = ScheduledDeletion.schedule(delete_project, days=0)
+        deletion.update(in_progress=True)
+
+        with self.tasks():
+            run_deletion(deletion.id)
+
+        self.get_success_response(org.slug)