Browse Source

fix(api) Don't return pending deletion projects in org details (#12556)

Filter the projects and teams coming from access to exclude those that
are pending deletion.

Fixes SEN-419
Mark Story 6 years ago
parent
commit
d323d3009b

+ 36 - 17
src/sentry/api/serializers/models/organization.py

@@ -118,30 +118,49 @@ class DetailedOrganizationSerializer(OrganizationSerializer):
     def get_attrs(self, item_list, user, **kwargs):
         return super(DetailedOrganizationSerializer, self).get_attrs(item_list, user)
 
-    def serialize(self, obj, attrs, user, access):
-        from sentry import experiments
-        from sentry.api.serializers.models.project import ProjectSummarySerializer
-        from sentry.api.serializers.models.team import TeamSerializer
+    def _project_list(self, organization, access):
+        member_project_ids = []
+        member_projects = []
+        for project in access.projects:
+            if project.status == ProjectStatus.VISIBLE:
+                member_project_ids.append(project.id)
+                member_projects.append(project)
+
+        other_projects = list(Project.objects.filter(
+            organization=organization,
+            status=ProjectStatus.VISIBLE,
+        ).exclude(id__in=member_project_ids))
+        project_list = sorted(other_projects + member_projects, key=lambda x: x.slug)
+
+        for project in project_list:
+            project._organization_cache = organization
+        return project_list
+
+    def _team_list(self, organization, access):
+        member_team_ids = []
+        member_teams = []
+        for team in access.teams:
+            if team.status == TeamStatus.VISIBLE:
+                member_team_ids.append(team.id)
+                member_teams.append(team)
 
-        member_teams = [team.id for team in access.teams]
         other_teams = list(Team.objects.filter(
-            organization=obj,
+            organization=organization,
             status=TeamStatus.VISIBLE,
-        ).exclude(id__in=member_teams))
-        team_list = sorted(other_teams + list(access.teams), key=lambda x: x.slug)
+        ).exclude(id__in=member_team_ids))
+        team_list = sorted(other_teams + member_teams, key=lambda x: x.slug)
 
         for team in team_list:
-            team._organization_cache = obj
+            team._organization_cache = organization
+        return team_list
 
-        member_projects = [project.id for project in access.projects]
-        other_projects = list(Project.objects.filter(
-            organization=obj,
-            status=ProjectStatus.VISIBLE,
-        ).exclude(id__in=member_projects))
-        project_list = sorted(other_projects + list(access.projects), key=lambda x: x.slug)
+    def serialize(self, obj, attrs, user, access):
+        from sentry import experiments
+        from sentry.api.serializers.models.project import ProjectSummarySerializer
+        from sentry.api.serializers.models.team import TeamSerializer
 
-        for project in project_list:
-            project._organization_cache = obj
+        team_list = self._team_list(obj, access)
+        project_list = self._project_list(obj, access)
 
         onboarding_tasks = list(
             OrganizationOnboardingTask.objects.filter(

+ 24 - 3
tests/sentry/api/endpoints/test_organization_details.py

@@ -16,6 +16,7 @@ from sentry.models import (
     Authenticator,
     AuthProvider,
     DeletedOrganization,
+    ObjectStatus,
     Organization,
     OrganizationAvatar,
     OrganizationOption,
@@ -53,12 +54,26 @@ class OrganizationDetailsTest(APITestCase):
         # Create non-member team to test response shape
         self.create_team(name='no-member', organization=org)
 
+        # Ensure deleted teams don't come back.
+        self.create_team(
+            name='deleted',
+            organization=org,
+            members=[user],
+            status=ObjectStatus.PENDING_DELETION)
+
         # Some projects with membership and some without.
-        for i in range(3):
+        for i in range(2):
             self.create_project(organization=org, teams=[team])
         for i in range(2):
             self.create_project(organization=org)
 
+        # Should not show up.
+        self.create_project(
+            slug='deleted',
+            organization=org,
+            teams=[team],
+            status=ObjectStatus.PENDING_DELETION)
+
         url = reverse(
             'sentry-api-0-organization-details', kwargs={
                 'organization_slug': org.slug,
@@ -72,8 +87,14 @@ class OrganizationDetailsTest(APITestCase):
             from django.db import connections
             response = self.client.get(url, format='json')
             pprint(connections['default'].queries)
-        assert len(response.data['projects']) == 5
-        assert len(response.data['teams']) == 2
+
+        project_slugs = [p['slug'] for p in response.data['projects']]
+        assert len(project_slugs) == 4
+        assert 'deleted' not in project_slugs
+
+        team_slugs = [t['slug'] for t in response.data['teams']]
+        assert len(team_slugs) == 2
+        assert 'deleted' not in team_slugs
 
     def test_as_superuser(self):
         self.user = self.create_user('super@example.org', is_superuser=True)