Browse Source

ref(teams): Use ProjectTeam relation instead of project.team

remove outdated todo

fix tests

add a few more todos, remove team slug from email headers

update ProjectView to inherit from org view instead of team

have project serializer use new relation

fix mysql tests

update test fixtures to use teams kwarg

stop writing team to deleted project audit

remove todo i handled in a different PR

remove team x header

make fixtures create_project backwards compatible for other repos

matt pr feedback
Jess MacQueen 7 years ago
parent
commit
6a49f5e71e

+ 1 - 1
api-docs/generator.py

@@ -167,7 +167,7 @@ def cli(output_path):
         projects = []
         for project_name in 'Pump Station', 'Prime Mover':
             report('project', 'Creating project "%s"' % project_name)
-            project = utils.create_project(project_name, team=team, org=org)
+            project = utils.create_project(project_name, teams=[team], org=org)
             release = utils.create_release(project=project, user=user)
             report('event', 'Creating event for "%s"' % project_name)
 

+ 7 - 2
src/sentry/api/bases/organization.py

@@ -9,7 +9,7 @@ from sentry.app import raven
 from sentry.auth import access
 from sentry.auth.superuser import is_active_superuser
 from sentry.models import (
-    ApiKey, Organization, OrganizationMemberTeam, Project, ReleaseProject, Team
+    ApiKey, Organization, OrganizationMemberTeam, Project, ProjectTeam, ReleaseProject, Team
 )
 from sentry.utils import auth
 
@@ -157,7 +157,12 @@ class OrganizationReleasesBaseEndpoint(OrganizationEndpoint):
             ).values_list(
                 'team_id', flat=True
             )
-        return Project.objects.filter(team_id__in=allowed_teams)
+
+        return Project.objects.filter(
+            id__in=ProjectTeam.objects.filter(
+                team_id__in=allowed_teams,
+            ).values_list('project_id', flat=True)
+        )
 
     def has_release_permission(self, request, organization, release):
         return ReleaseProject.objects.filter(

+ 2 - 2
src/sentry/api/bases/organizationissues.py

@@ -33,9 +33,9 @@ class OrganizationIssuesEndpoint(OrganizationMemberEndpoint, EnvironmentMixin):
 
         project_list = Project.objects.filter(
             organization=organization,
-            team__in=OrganizationMemberTeam.objects.filter(
+            teams__in=OrganizationMemberTeam.objects.filter(
                 organizationmember=member,
-            ).values('team')
+            ).values('team'),
         )
 
         queryset = self.get_queryset(request, organization, member, project_list)

+ 13 - 6
src/sentry/api/bases/project.py

@@ -5,10 +5,11 @@ from sentry.api.exceptions import ResourceDoesNotExist
 from sentry.app import raven
 from sentry.models import Project, ProjectStatus
 
-from .team import TeamPermission
+from .organization import OrganizationPermission
+from .team import has_team_permission
 
 
-class ProjectPermission(TeamPermission):
+class ProjectPermission(OrganizationPermission):
     scope_map = {
         'GET': ['project:read', 'project:write', 'project:admin'],
         'POST': ['project:write', 'project:admin'],
@@ -17,7 +18,15 @@ class ProjectPermission(TeamPermission):
     }
 
     def has_object_permission(self, request, view, project):
-        return super(ProjectPermission, self).has_object_permission(request, view, project.team)
+        result = super(ProjectPermission,
+                       self).has_object_permission(request, view, project.organization)
+
+        if not result:
+            return result
+
+        return any(
+            has_team_permission(request, team, self.scope_map) for team in project.teams.all()
+        )
 
 
 class StrictProjectPermission(ProjectPermission):
@@ -74,15 +83,13 @@ class ProjectEndpoint(Endpoint):
             project = Project.objects.filter(
                 organization__slug=organization_slug,
                 slug=project_slug,
-            ).select_related('organization', 'team').get()
+            ).select_related('organization').prefetch_related('teams').get()
         except Project.DoesNotExist:
             raise ResourceDoesNotExist
 
         if project.status != ProjectStatus.VISIBLE:
             raise ResourceDoesNotExist
 
-        project.team.organization = project.organization
-
         self.check_object_permissions(request, project)
 
         raven.tags_context({

+ 9 - 5
src/sentry/api/bases/team.py

@@ -8,6 +8,14 @@ from sentry.models import Team, TeamStatus
 from .organization import OrganizationPermission
 
 
+def has_team_permission(request, team, scope_map):
+    if not (request.user and request.user.is_authenticated()) and request.auth:
+        return request.auth.organization_id == team.organization.id
+
+    allowed_scopes = set(scope_map.get(request.method, []))
+    return any(request.access.has_team_scope(team, s) for s in allowed_scopes)
+
+
 class TeamPermission(OrganizationPermission):
     scope_map = {
         'GET': ['team:read', 'team:write', 'team:admin'],
@@ -22,11 +30,7 @@ class TeamPermission(OrganizationPermission):
         if not result:
             return result
 
-        if not (request.user and request.user.is_authenticated()) and request.auth:
-            return request.auth.organization_id == team.organization.id
-
-        allowed_scopes = set(self.scope_map.get(request.method, []))
-        return any(request.access.has_team_scope(team, s) for s in allowed_scopes)
+        return has_team_permission(request, team, self.scope_map)
 
 
 class TeamEndpoint(Endpoint):

+ 1 - 1
src/sentry/api/endpoints/organization_activity.py

@@ -12,7 +12,7 @@ class OrganizationActivityEndpoint(OrganizationMemberEndpoint, EnvironmentMixin)
         queryset = Activity.objects.filter(
             project__in=Project.objects.filter(
                 organization=organization,
-                team__in=OrganizationMemberTeam.objects.filter(
+                teams__in=OrganizationMemberTeam.objects.filter(
                     organizationmember=member,
                 ).values('team')
             )

+ 6 - 6
src/sentry/api/endpoints/organization_projects.py

@@ -54,18 +54,18 @@ class OrganizationProjectsEndpoint(OrganizationEndpoint):
         if request.auth and not request.user.is_authenticated():
             # TODO: remove this, no longer supported probably
             if hasattr(request.auth, 'project'):
-                team_list = [request.auth.project.team]
+                team_list = list(request.auth.project.teams.all())
                 queryset = queryset = Project.objects.filter(
                     id=request.auth.project.id,
-                ).select_related('team')
+                ).prefetch_related('teams')
             elif request.auth.organization is not None:
                 org = request.auth.organization
                 team_list = list(Team.objects.filter(
                     organization=org,
                 ))
                 queryset = Project.objects.filter(
-                    team__in=team_list,
-                ).select_related('team')
+                    teams__in=team_list,
+                ).prefetch_related('teams')
             else:
                 return Response(
                     {
@@ -76,8 +76,8 @@ class OrganizationProjectsEndpoint(OrganizationEndpoint):
         else:
             team_list = list(request.access.teams)
             queryset = Project.objects.filter(
-                team__in=team_list,
-            ).select_related('team')
+                teams__in=team_list,
+            ).prefetch_related('team')
 
         return self.paginate(
             request=request,

+ 1 - 1
src/sentry/api/endpoints/organization_stats.py

@@ -61,7 +61,7 @@ class OrganizationStatsEndpoint(OrganizationEndpoint, EnvironmentMixin, StatsMix
                     team=team,
                     user=request.user,
                 ))
-            keys = [p.id for p in project_list]
+            keys = list({p.id for p in project_list})
         else:
             raise ValueError('Invalid group: %s' % group)
 

+ 10 - 3
src/sentry/api/endpoints/organization_user_issues.py

@@ -7,7 +7,7 @@ from sentry.api.base import EnvironmentMixin
 from sentry.api.bases.organization import OrganizationEndpoint
 from sentry.api.serializers import serialize
 from sentry.api.serializers.models.group import TagBasedStreamGroupSerializer
-from sentry.models import (EventUser, Group, Project)
+from sentry.models import (EventUser, Group, ProjectTeam, Team)
 
 
 class OrganizationUserIssuesEndpoint(OrganizationEndpoint, EnvironmentMixin):
@@ -21,8 +21,15 @@ class OrganizationUserIssuesEndpoint(OrganizationEndpoint, EnvironmentMixin):
         )
         # they have organization access but not to this project, thus
         # they shouldn't be able to see this user
-        if not request.access.has_team_access(
-                Project.objects.select_related('team').get(pk=euser.project_id).team):
+        teams = Team.objects.filter(
+            organization=organization,
+            id__in=ProjectTeam.objects.filter(
+                project_id=euser.project_id,
+            ).values_list('team_id', flat=True)
+        )
+        has_team_access = any([request.access.has_team_access(t) for t in teams])
+
+        if not has_team_access:
             return Response([])
 
         other_eusers = euser.find_similar_users(request.user)

+ 1 - 1
src/sentry/api/endpoints/organization_user_issues_search.py

@@ -22,7 +22,7 @@ class OrganizationUserIssuesSearchEndpoint(OrganizationEndpoint, EnvironmentMixi
         # limit to only teams user has opted into
         project_ids = list(
             Project.objects.filter(
-                team__in=OrganizationMemberTeam.objects.filter(
+                teams__in=OrganizationMemberTeam.objects.filter(
                     organizationmember__user=request.user,
                     organizationmember__organization=organization,
                     is_active=True,

Some files were not shown because too many files changed in this diff