Browse Source

Start work on import post request

David Burke 2 years ago
parent
commit
86ef4c6604

+ 12 - 5
glitchtip/importer/importer.py

@@ -23,13 +23,17 @@ class GlitchTipImporter:
     faked and used to elevate privileges. Always confirm new data is associated with
     appropriate organization. Also assume user is at least an org admin, no need to
     double check permissions when creating assets within the organization.
+
+    create_users should be False unless running as superuser/management command
     """
 
-    def __init__(self, url: str, auth_token: str, organization_slug: str):
+    def __init__(
+        self, url: str, auth_token: str, organization_slug: str, create_users=False
+    ):
         self.api_root_url = reverse("api-root-view")
         self.url = url
         self.headers = {"Authorization": f"Bearer {auth_token}"}
-        self.create_users = True  # Very unsafe outside of superuser usage
+        self.create_users = create_users
         self.organization_slug = organization_slug
         self.organization_id = None
         self.organization_url = reverse(
@@ -48,9 +52,12 @@ class GlitchTipImporter:
             kwargs={"organization_slug": self.organization_slug},
         )
 
-    def run(self):
-        self.check_auth()
-        self.import_organization()
+    def run(self, organization_id=None):
+        """Set organization_id to None to import (superuser only)"""
+        if organization_id is None:
+            self.import_organization()
+        else:
+            organization_id = organization_id
         self.import_organization_users()
         self.import_projects()
         self.import_teams()

+ 2 - 1
glitchtip/importer/management/commands/import.py

@@ -16,6 +16,7 @@ class Command(BaseCommand):
         if not url.startswith("http"):
             url = "https://" + url
         importer = GlitchTipImporter(
-            url, options["auth_token"], options["organization_slug"]
+            url, options["auth_token"], options["organization_slug"], create_users=True
         )
+        importer.check_auth()
         importer.run()

+ 17 - 0
glitchtip/importer/serializers.py

@@ -0,0 +1,17 @@
+from rest_framework import serializers
+from organizations_ext.models import Organization
+
+
+class ImportSerializer(serializers.Serializer):
+    url = serializers.URLField()
+    authToken = serializers.CharField()
+    organizationSlug = serializers.SlugRelatedField(
+        slug_field="slug", queryset=Organization.objects.none()
+    )
+
+    def __init__(self, context, *args, **kwargs):
+        if user := context["request"].user:
+            self.fields[
+                "organizationSlug"
+            ].queryset = user.organizations_ext_organization.all()
+        return super().__init__(*args, **kwargs)

+ 34 - 13
glitchtip/importer/tests.py

@@ -1,5 +1,6 @@
 import requests_mock
 from django.core.management import call_command
+from django.urls import reverse
 
 from glitchtip.test_utils.test_case import GlitchTipTestCase
 from projects.models import Project
@@ -9,13 +10,16 @@ from .importer import GlitchTipImporter
 
 
 class ImporterTestCase(GlitchTipTestCase):
+    def setUp(self):
+        self.url = "https://example.com"
+        self.org_name = "org"
+        self.auth_token = "token"
+        self.importer = GlitchTipImporter(
+            self.url.lstrip("htps:/"), self.auth_token, self.org_name
+        )
+
     @requests_mock.Mocker()
     def test_import_command(self, m):
-        url = "https://example.com"
-        org_name = "org"
-        auth_token = "token"
-        importer = GlitchTipImporter(url.lstrip("htps:/"), auth_token, org_name)
-
         project = {"id": "1", "slug": "project", "name": "project"}
         key = {
             "id": "a" * 32,
@@ -23,13 +27,13 @@ class ImporterTestCase(GlitchTipTestCase):
             "projectID": 1,
             "label": "Default",
         }
-        m.get(url + importer.api_root_url, json={"user": {"username": "foo"}})
-        m.get(url + importer.organization_url, json={"id": 1})
-        m.get(url + importer.organization_users_url, json=[])
-        m.get(url + importer.projects_url, json=[project])
-        m.get(url + "/api/0/projects/org/project/keys/", json=[key])
+        m.get(self.url + self.importer.api_root_url, json={"user": {"username": "foo"}})
+        m.get(self.url + self.importer.organization_url, json={"id": 1})
+        m.get(self.url + self.importer.organization_users_url, json=[])
+        m.get(self.url + self.importer.projects_url, json=[project])
+        m.get(self.url + "/api/0/projects/org/project/keys/", json=[key])
         m.get(
-            url + importer.teams_url,
+            self.url + self.importer.teams_url,
             json=[
                 {
                     "id": "1",
@@ -38,9 +42,9 @@ class ImporterTestCase(GlitchTipTestCase):
                 }
             ],
         )
-        m.get(url + "/api/0/teams/org/team/members/", json=[])
+        m.get(self.url + "/api/0/teams/org/team/members/", json=[])
 
-        call_command("import", url, auth_token, org_name)
+        call_command("import", self.url, self.auth_token, self.org_name)
         self.assertTrue(Team.objects.filter(slug="team").exists())
         self.assertTrue(
             Project.objects.filter(
@@ -49,3 +53,20 @@ class ImporterTestCase(GlitchTipTestCase):
                 projectkey__public_key=key["public"],
             ).exists()
         )
+
+    @requests_mock.Mocker()
+    def test_view(self, m):
+        self.create_user_and_project()
+        self.organization.slug = self.org_name
+        self.organization.save()
+        url = reverse("import")
+        data = {
+            "url": self.url,
+            "authToken": self.auth_token,
+            "organizationSlug": self.org_name,
+        }
+        res = self.client.options(url)
+        print(res.data)
+        res = self.client.post(url, data)
+        print(res.data)
+        self.assertEqual(res.status_code, 200)

+ 5 - 0
glitchtip/importer/urls.py

@@ -0,0 +1,5 @@
+from django.urls import path
+from .views import ImportAPIView
+
+
+urlpatterns = [path("import", ImportAPIView.as_view(), name="import")]

+ 23 - 0
glitchtip/importer/views.py

@@ -0,0 +1,23 @@
+from rest_framework import views
+from rest_framework.response import Response
+
+from .serializers import ImportSerializer
+from .importer import GlitchTipImporter
+
+
+class ImportAPIView(views.APIView):
+    serializer_class = ImportSerializer
+
+    def post(self, request):
+        serializer = self.serializer_class(
+            data=request.data, context={"request": request}
+        )
+        serializer.is_valid(raise_exception=True)
+        data = serializer.validated_data
+        importer = GlitchTipImporter(
+            data["url"], data["authToken"], data["organizationSlug"]
+        )
+        importer.check_auth()
+        importer.run(organization_id=data["organizationSlug"].pk)
+
+        return Response()

+ 3 - 2
glitchtip/urls.py

@@ -79,13 +79,14 @@ urlpatterns += [
     path("api/0/", include("projects.urls")),
     path("api/0/", include("issues.urls")),
     path("api/0/", include("users.urls")),
-    path("api/0/", include("glitchtip.stats.urls")),
     path("api/0/", include("organizations_ext.urls")),
     path("api/0/", include("teams.urls")),
     path("api/0/", include("api_tokens.urls")),
     path("api/0/", include("files.urls")),
-    path("api/0/", include("glitchtip.uptime.urls")),
     path("api/0/", include("difs.urls")),
+    path("api/0/", include("glitchtip.importer.urls")),
+    path("api/0/", include("glitchtip.stats.urls")),
+    path("api/0/", include("glitchtip.uptime.urls")),
     path("api/0/", include("glitchtip.wizard.urls")),
     path("api/mfa/", include("django_rest_mfa.urls")),
     path("api/", include("events.urls")),