Browse Source

feat(api): Allow to change team of a project via API

Jiangge Zhang 7 years ago
parent
commit
ccc4d21710

+ 1 - 0
CHANGES

@@ -3,6 +3,7 @@ Version 8.21 (Unreleased)
 
 - Ignore querystrings when looking up release artifacts
 - Add Visual Studio authentication provider for plugins.
+- Add "team" parameter to the project details API.
 
 Version 8.20
 ------------

+ 22 - 1
src/sentry/api/endpoints/project_details.py

@@ -17,7 +17,8 @@ from sentry.api.decorators import sudo_required
 from sentry.api.serializers import serialize
 from sentry.api.serializers.models.project import DetailedProjectSerializer
 from sentry.models import (
-    AuditLogEntryEvent, Group, GroupStatus, Project, ProjectBookmark, ProjectStatus, UserOption
+    AuditLogEntryEvent, Group, GroupStatus, Project, ProjectBookmark, ProjectStatus,
+    UserOption, Team,
 )
 from sentry.tasks.deletion import delete_project
 from sentry.utils.apidocs import scenario, attach_scenarios
@@ -78,6 +79,7 @@ class ProjectAdminSerializer(serializers.Serializer):
     isSubscribed = serializers.BooleanField()
     name = serializers.CharField(max_length=200)
     slug = serializers.RegexField(r'^[a-z0-9_\-]+$', max_length=50)
+    team = serializers.RegexField(r'^[a-z0-9_\-]+$', max_length=50)
     digestsMinDelay = serializers.IntegerField(min_value=60, max_value=3600)
     digestsMaxDelay = serializers.IntegerField(min_value=60, max_value=3600)
     subjectPrefix = serializers.CharField(max_length=200)
@@ -157,6 +159,7 @@ class ProjectDetailsEndpoint(ProjectEndpoint):
         :pparam string project_slug: the slug of the project to delete.
         :param string name: the new name for the project.
         :param string slug: the new slug for the project.
+        :param string team: the slug of new team for the project.
         :param string platform: the new platform for the project.
         :param boolean isBookmarked: in case this API call is invoked with a
                                      user context this allows changing of
@@ -202,6 +205,24 @@ class ProjectDetailsEndpoint(ProjectEndpoint):
             project.name = result['name']
             changed = True
 
+        if result.get('team'):
+            team_list = [
+                t for t in Team.objects.get_for_user(
+                    organization=project.organization,
+                    user=request.user,
+                )
+                if request.access.has_team_scope(t, 'project:write')
+                if t.slug == result['team']
+            ]
+            if not team_list:
+                return Response(
+                    {
+                        'detail': ['The new team is not found.']
+                    }, status=400
+                )
+            project.team = team_list[0]
+            changed = True
+
         if result.get('platform'):
             project.platform = result['platform']
             changed = True

+ 40 - 0
tests/sentry/api/endpoints/test_project_details.py

@@ -88,6 +88,46 @@ class ProjectUpdateTest(APITestCase):
         assert project.slug == 'foobar'
         assert project.platform == 'cocoa'
 
+    def test_team_changes(self):
+        project = self.create_project()
+        team = self.create_team()
+        self.login_as(user=self.user)
+        url = reverse(
+            'sentry-api-0-project-details',
+            kwargs={
+                'organization_slug': project.organization.slug,
+                'project_slug': project.slug,
+            }
+        )
+        resp = self.client.put(
+            url, data={
+                'team': team.slug,
+            }
+        )
+        assert resp.status_code == 200, resp.content
+        project = Project.objects.get(id=project.id)
+        assert project.team == team
+
+    def test_team_changes_not_found(self):
+        project = self.create_project()
+        self.login_as(user=self.user)
+        url = reverse(
+            'sentry-api-0-project-details',
+            kwargs={
+                'organization_slug': project.organization.slug,
+                'project_slug': project.slug,
+            }
+        )
+        resp = self.client.put(
+            url, data={
+                'team': 'the-team-that-does-not-exist',
+            }
+        )
+        assert resp.status_code == 400, resp.content
+        assert resp.data['detail'][0] == 'The new team is not found.'
+        project = Project.objects.get(id=project.id)
+        assert project.team == self.team
+
     def test_member_changes(self):
         project = self.create_project()
         user = self.create_user('bar@example.com')