|
@@ -1,5 +1,6 @@
|
|
-import requests
|
|
|
|
|
|
+import aiohttp
|
|
import tablib
|
|
import tablib
|
|
|
|
+from asgiref.sync import sync_to_async
|
|
from django.db.models import Q
|
|
from django.db.models import Q
|
|
from django.urls import reverse
|
|
from django.urls import reverse
|
|
|
|
|
|
@@ -7,6 +8,7 @@ from apps.organizations_ext.admin import OrganizationResource, OrganizationUserR
|
|
from apps.organizations_ext.models import OrganizationUser, OrganizationUserRole
|
|
from apps.organizations_ext.models import OrganizationUser, OrganizationUserRole
|
|
from apps.projects.admin import ProjectKeyResource, ProjectResource
|
|
from apps.projects.admin import ProjectKeyResource, ProjectResource
|
|
from apps.projects.models import Project
|
|
from apps.projects.models import Project
|
|
|
|
+from apps.shared.types import TypeJson
|
|
from apps.teams.admin import TeamResource
|
|
from apps.teams.admin import TeamResource
|
|
from apps.users.admin import UserResource
|
|
from apps.users.admin import UserResource
|
|
from apps.users.models import User
|
|
from apps.users.models import User
|
|
@@ -30,8 +32,7 @@ class GlitchTipImporter:
|
|
def __init__(
|
|
def __init__(
|
|
self, url: str, auth_token: str, organization_slug: str, create_users=False
|
|
self, url: str, auth_token: str, organization_slug: str, create_users=False
|
|
):
|
|
):
|
|
- self.api_root_url = reverse("api-root-view")
|
|
|
|
- self.url = url
|
|
|
|
|
|
+ self.url = url.rstrip("/")
|
|
self.headers = {"Authorization": f"Bearer {auth_token}"}
|
|
self.headers = {"Authorization": f"Bearer {auth_token}"}
|
|
self.create_users = create_users
|
|
self.create_users = create_users
|
|
self.organization_slug = organization_slug
|
|
self.organization_slug = organization_slug
|
|
@@ -52,32 +53,34 @@ class GlitchTipImporter:
|
|
kwargs={"organization_slug": self.organization_slug},
|
|
kwargs={"organization_slug": self.organization_slug},
|
|
)
|
|
)
|
|
|
|
|
|
- def run(self, organization_id=None):
|
|
|
|
|
|
+ async def run(self, organization_id=None):
|
|
"""Set organization_id to None to import (superuser only)"""
|
|
"""Set organization_id to None to import (superuser only)"""
|
|
if organization_id is None:
|
|
if organization_id is None:
|
|
- self.import_organization()
|
|
|
|
|
|
+ await self.import_organization()
|
|
else:
|
|
else:
|
|
self.organization_id = organization_id
|
|
self.organization_id = organization_id
|
|
- self.import_organization_users()
|
|
|
|
- self.import_projects()
|
|
|
|
- self.import_teams()
|
|
|
|
|
|
+ await self.import_organization_users()
|
|
|
|
+ await self.import_projects()
|
|
|
|
+ await self.import_teams()
|
|
|
|
|
|
- def get(self, url):
|
|
|
|
- return requests.get(url, headers=self.headers)
|
|
|
|
|
|
+ async def get(self, url: str) -> TypeJson:
|
|
|
|
+ async with aiohttp.ClientSession() as session:
|
|
|
|
+ async with session.get(url, headers=self.headers) as res:
|
|
|
|
+ return await res.json()
|
|
|
|
|
|
- def import_organization(self):
|
|
|
|
|
|
+ async def import_organization(self):
|
|
resource = OrganizationResource()
|
|
resource = OrganizationResource()
|
|
- res = self.get(self.url + self.organization_url)
|
|
|
|
- data = res.json()
|
|
|
|
|
|
+ data = await self.get(self.url + self.organization_url)
|
|
self.organization_id = data["id"] # TODO unsafe for web usage
|
|
self.organization_id = data["id"] # TODO unsafe for web usage
|
|
dataset = tablib.Dataset()
|
|
dataset = tablib.Dataset()
|
|
dataset.dict = [data]
|
|
dataset.dict = [data]
|
|
- resource.import_data(dataset, raise_errors=True)
|
|
|
|
|
|
+ await sync_to_async(resource.import_data)(dataset, raise_errors=True)
|
|
|
|
|
|
- def import_organization_users(self):
|
|
|
|
|
|
+ async def import_organization_users(self):
|
|
resource = OrganizationUserResource()
|
|
resource = OrganizationUserResource()
|
|
- res = self.get(self.url + self.organization_users_url)
|
|
|
|
- org_users = res.json()
|
|
|
|
|
|
+ org_users = await self.get(self.url + self.organization_users_url)
|
|
|
|
+ if not org_users:
|
|
|
|
+ return
|
|
if self.create_users:
|
|
if self.create_users:
|
|
user_resource = UserResource()
|
|
user_resource = UserResource()
|
|
users_list = [
|
|
users_list = [
|
|
@@ -89,7 +92,7 @@ class GlitchTipImporter:
|
|
]
|
|
]
|
|
dataset = tablib.Dataset()
|
|
dataset = tablib.Dataset()
|
|
dataset.dict = users
|
|
dataset.dict = users
|
|
- user_resource.import_data(dataset, raise_errors=True)
|
|
|
|
|
|
+ await sync_to_async(user_resource.import_data)(dataset, raise_errors=True)
|
|
|
|
|
|
for org_user in org_users:
|
|
for org_user in org_users:
|
|
org_user["organization"] = self.organization_id
|
|
org_user["organization"] = self.organization_id
|
|
@@ -104,17 +107,16 @@ class GlitchTipImporter:
|
|
org_user["user"] = None
|
|
org_user["user"] = None
|
|
dataset = tablib.Dataset()
|
|
dataset = tablib.Dataset()
|
|
dataset.dict = org_users
|
|
dataset.dict = org_users
|
|
- resource.import_data(dataset, raise_errors=True)
|
|
|
|
|
|
+ await sync_to_async(resource.import_data)(dataset, raise_errors=True)
|
|
|
|
|
|
- def import_projects(self):
|
|
|
|
|
|
+ async def import_projects(self):
|
|
project_resource = ProjectResource()
|
|
project_resource = ProjectResource()
|
|
project_key_resource = ProjectKeyResource()
|
|
project_key_resource = ProjectKeyResource()
|
|
- res = self.get(self.url + self.projects_url)
|
|
|
|
- projects = res.json()
|
|
|
|
|
|
+ projects = await self.get(self.url + self.projects_url)
|
|
project_keys = []
|
|
project_keys = []
|
|
for project in projects:
|
|
for project in projects:
|
|
project["organization"] = self.organization_id
|
|
project["organization"] = self.organization_id
|
|
- keys = self.get(
|
|
|
|
|
|
+ keys = await self.get(
|
|
self.url
|
|
self.url
|
|
+ reverse(
|
|
+ reverse(
|
|
"project-keys-list",
|
|
"project-keys-list",
|
|
@@ -122,46 +124,53 @@ class GlitchTipImporter:
|
|
"project_pk": f"{self.organization_slug}/{project['slug']}",
|
|
"project_pk": f"{self.organization_slug}/{project['slug']}",
|
|
},
|
|
},
|
|
)
|
|
)
|
|
- ).json()
|
|
|
|
|
|
+ )
|
|
for key in keys:
|
|
for key in keys:
|
|
key["project"] = project["id"]
|
|
key["project"] = project["id"]
|
|
key["public_key"] = key["public"]
|
|
key["public_key"] = key["public"]
|
|
project_keys += keys
|
|
project_keys += keys
|
|
dataset = tablib.Dataset()
|
|
dataset = tablib.Dataset()
|
|
dataset.dict = projects
|
|
dataset.dict = projects
|
|
- project_resource.import_data(dataset, raise_errors=True)
|
|
|
|
- owned_project_ids = Project.objects.filter(
|
|
|
|
- organization_id=self.organization_id,
|
|
|
|
- pk__in=[d["projectId"] for d in project_keys],
|
|
|
|
- ).values_list("pk", flat=True)
|
|
|
|
|
|
+ await sync_to_async(project_resource.import_data)(dataset, raise_errors=True)
|
|
|
|
+ owned_project_ids = [
|
|
|
|
+ pk
|
|
|
|
+ async for pk in Project.objects.filter(
|
|
|
|
+ organization_id=self.organization_id,
|
|
|
|
+ pk__in=[d["projectId"] for d in project_keys],
|
|
|
|
+ ).values_list("pk", flat=True)
|
|
|
|
+ ]
|
|
project_keys = list(
|
|
project_keys = list(
|
|
filter(lambda key: key["projectId"] in owned_project_ids, project_keys)
|
|
filter(lambda key: key["projectId"] in owned_project_ids, project_keys)
|
|
)
|
|
)
|
|
dataset.dict = project_keys
|
|
dataset.dict = project_keys
|
|
- project_key_resource.import_data(dataset, raise_errors=True)
|
|
|
|
|
|
+ await sync_to_async(project_key_resource.import_data)(
|
|
|
|
+ dataset, raise_errors=True
|
|
|
|
+ )
|
|
|
|
|
|
- def import_teams(self):
|
|
|
|
|
|
+ async def import_teams(self):
|
|
resource = TeamResource()
|
|
resource = TeamResource()
|
|
- res = self.get(self.url + self.teams_url)
|
|
|
|
- teams = res.json()
|
|
|
|
|
|
+ teams = await self.get(self.url + self.teams_url)
|
|
for team in teams:
|
|
for team in teams:
|
|
team["organization"] = self.organization_id
|
|
team["organization"] = self.organization_id
|
|
team["projects"] = ",".join(
|
|
team["projects"] = ",".join(
|
|
map(
|
|
map(
|
|
str,
|
|
str,
|
|
- Project.objects.filter(
|
|
|
|
- organization_id=self.organization_id,
|
|
|
|
- pk__in=[int(d["id"]) for d in team["projects"]],
|
|
|
|
- ).values_list("id", flat=True),
|
|
|
|
|
|
+ [
|
|
|
|
+ pk
|
|
|
|
+ async for pk in Project.objects.filter(
|
|
|
|
+ organization_id=self.organization_id,
|
|
|
|
+ pk__in=[int(d["id"]) for d in team["projects"]],
|
|
|
|
+ ).values_list("id", flat=True)
|
|
|
|
+ ],
|
|
)
|
|
)
|
|
)
|
|
)
|
|
- team_members = self.get(
|
|
|
|
|
|
+ team_members = await self.get(
|
|
self.url
|
|
self.url
|
|
+ reverse(
|
|
+ reverse(
|
|
"team-members-list",
|
|
"team-members-list",
|
|
kwargs={"team_pk": f"{self.organization_slug}/{team['slug']}"},
|
|
kwargs={"team_pk": f"{self.organization_slug}/{team['slug']}"},
|
|
)
|
|
)
|
|
- ).json()
|
|
|
|
|
|
+ )
|
|
team_member_emails = [d["email"] for d in team_members]
|
|
team_member_emails = [d["email"] for d in team_members]
|
|
team["members"] = ",".join(
|
|
team["members"] = ",".join(
|
|
[
|
|
[
|
|
@@ -178,10 +187,11 @@ class GlitchTipImporter:
|
|
)
|
|
)
|
|
dataset = tablib.Dataset()
|
|
dataset = tablib.Dataset()
|
|
dataset.dict = teams
|
|
dataset.dict = teams
|
|
- resource.import_data(dataset, raise_errors=True)
|
|
|
|
|
|
+ await sync_to_async(resource.import_data)(dataset, raise_errors=True)
|
|
|
|
|
|
- def check_auth(self):
|
|
|
|
- res = requests.get(self.url + self.api_root_url, headers=self.headers)
|
|
|
|
- data = res.json()
|
|
|
|
- if res.status_code != 200 or not data["user"]:
|
|
|
|
- raise ImporterException("Bad auth token")
|
|
|
|
|
|
+ async def check_auth(self):
|
|
|
|
+ async with aiohttp.ClientSession() as session:
|
|
|
|
+ async with session.get(self.url + "/api/0/", headers=self.headers) as res:
|
|
|
|
+ data = await res.json()
|
|
|
|
+ if res.status != 200 or not data["user"]:
|
|
|
|
+ raise ImporterException("Bad auth token")
|