Skip to content

Commit

Permalink
Merge pull request #797 from longguikeji/feature-arkstore-install
Browse files Browse the repository at this point in the history
Feature arkstore install
  • Loading branch information
luolu-lg authored Apr 29, 2022
2 parents f744959 + 012e80c commit 4355fb0
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 140 deletions.
2 changes: 1 addition & 1 deletion api/v1/pages/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
'description': '购买'
},
'download': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/download/{id}/',
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/install/{id}/',
'method': 'get',
'description': '下载'
}
Expand Down
15 changes: 8 additions & 7 deletions api/v1/serializers/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ class ArkStoreExtensionSerializer(serializers.Serializer):

name = serializers.CharField()
description = serializers.CharField()
# version = serializers.CharField()
# homepage = serializers.CharField()
# logo = serializers.CharField()
author = serializers.CharField()
# tags = serializers.CharField()
# type = serializers.CharField()
# scope = serializers.CharField()
version = serializers.CharField()
homepage = serializers.CharField()
logo = serializers.CharField()
maintainer = serializers.CharField()
tags = serializers.CharField()
type = serializers.CharField()
scope = serializers.CharField()
uuid = serializers.UUIDField(default='')
purchased = serializers.CharField()
button = serializers.CharField()
14 changes: 12 additions & 2 deletions api/v1/urls/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@
name='arkstore',
),
re_path(
r'^tenant/(?P<tenant_uuid>[\w-]+)/arkstore/download/(?P<pk>[\w-]+)/$',
arkstore.ArkStoreDownloadView.as_view(),
r'^tenant/(?P<tenant_uuid>[\w-]+)/arkstore/install/(?P<pk>[\w-]+)/$',
arkstore.ArkStoreInstallView.as_view(),
name='arkstore',
),
re_path(
r'^tenant/(?P<tenant_uuid>[\w-]+)/arkstore/order/$',
arkstore.ArkStoreOrderView.as_view(),
name='arkstore',
),
re_path(
r'^tenant/(?P<tenant_uuid>[\w-]+)/arkstore/bind_agent/$',
arkstore.ArkStoreBindAgentView.as_view(),
name='arkstore',
),
re_path(
r'^tenant/(?P<tenant_uuid>[\w-]+)/arkstore/auto_fill_form/(?P<pk>[\w-]+)/$',
arkstore.ArkStoreGetAutoFormFillDataView.as_view(),
name='arkstore',
),
]
189 changes: 71 additions & 118 deletions api/v1/views/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework_expiring_authtoken.authentication import ExpiringTokenAuthentication
from perm.custom_access import ApiAccessPermission
from django.conf import settings
from collections import OrderedDict
import requests
from tenant.models import Tenant
from app.models import App
from common.code import Code
from common.arkstore import (
get_arkstore_access_token,
purcharse_arkstore_extension,
install_arkstore_extension,
bind_arkstore_agent,
get_arkstore_apps_and_extensions,
get_arkid_saas_app_detail,
)


@extend_schema(
Expand All @@ -28,30 +34,43 @@ class ArkStoreAPIView(ListAPIView):
pagination_class = DefaultListPaginator

def get_queryset(self):
page = self.request.query_params.get('page')
page_size = self.request.query_params.get('page_size')
# arkstore use offset and limit
if page and page_size:
limit = int(page_size)
offset = (int(page)-1) * int(page_size)
purchased = self.request.query_params.get('purchased')
token = self.request.user.token
tenant_uuid = self.kwargs['tenant_uuid']
tenant = Tenant.objects.get(uuid=tenant_uuid)
access_token = get_arkstore_access_token(tenant, token)
saas_extensions_data = get_arkstore_extensions(access_token, purchased)
# saas_extensions = []
# for extension_data in saas_extensions_data:
# extension = OrderedDict()
# extension.name = extension_data['name']
# extension.description = extension_data['description']
# extension.version = extension_data['version']
# extension.uuid = extension_data['uuid']
# extension.logo = extension_data['logo']
# extension.maintainer = extension_data['author']
# extension.purchased = '已购买' if extension_data['purchased'] == True else '未购买'
# extension.tags = ''
# extension.type = extension.name
# extension.scope = ''
# extension.homepage = ''
# saas_extensions.append(extension)

# return saas_extensions
return saas_extensions_data
saas_extensions_data = get_arkstore_apps_and_extensions(access_token, purchased, offset, limit)
saas_extensions_data = saas_extensions_data['items']
saas_extensions = []
for extension_data in saas_extensions_data:
extension = OrderedDict()
extension['name'] = extension_data['name']
extension['description'] = extension_data['description']
extension['version'] = extension_data['version']
extension['uuid'] = extension_data['uuid']
extension['logo'] = extension_data['logo']
extension['maintainer'] = extension_data['author']
# extension['purchased'] = '已购买' if extension_data['purchased'] == True else '未购买'
extension['purchased'] = extension_data['purchased']
if extension_data['upgrade']:
extension['button'] = '升级'
elif extension['purchased']:
extension['button'] = '安装'
else:
extension['button'] = '购买'
extension['tags'] = ''
extension['type'] = extension_data['type']
extension['scope'] = ''
extension['homepage'] = ''
saas_extensions.append(extension)

return saas_extensions


@extend_schema(roles=['globaladmin'], tags=['arkstore-extension'], summary='arkstore下单')
Expand All @@ -70,7 +89,7 @@ def post(self, request, tenant_uuid, *args, **kwargs):


@extend_schema(roles=['globaladmin'], tags=['arkstore-extension'], summary='arkstore下载插件')
class ArkStoreDownloadView(GenericAPIView):
class ArkStoreInstallView(GenericAPIView):

permission_classes = [IsAuthenticated, ApiAccessPermission]
authentication_classes = [ExpiringTokenAuthentication]
Expand All @@ -79,101 +98,35 @@ def get(self, request, tenant_uuid, *args, **kwargs):
extension_uuid = kwargs['pk']
token = request.user.token
tenant = Tenant.objects.get(uuid=tenant_uuid)
access_token = get_arkstore_access_token(tenant, token)
result = download_arkstore_extension(access_token, extension_uuid)
result = install_arkstore_extension(tenant, token, extension_uuid)
result = {'error': Code.OK.value}
return JsonResponse(result)


def get_saas_token(tenant, token):
"""
获取saas平台token
"""
app = App.active_objects.filter(name='arkid_saas', tenant=tenant).first()
data = app.data
url = data["authorize"]
params = {
"client_id": data["client_id"],
"redirect_uri": data["redirect_uris"],
"scope": "openid",
"response_type": "code",
"token": token,
}
resp = requests.get(url, params=params)
if resp.status_code != 200:
raise Exception(f'Error get_saas_token: {resp.status_code}')
resp = resp.json()
return resp['token'], resp['tenant_uuid'], resp['tenant_slug']


def get_arkstore_access_token(tenant, token):
"""
获取插件商店access_token
"""
saas_token, saas_tenant_uuid, saas_tenant_slug = get_saas_token(tenant, token)
params = {'state': 'client', 'tenant_slug': saas_tenant_slug, 'token': saas_token}
app_login_url = settings.ARKSTOER_URL + '/api/v1/login'
resp = requests.get(app_login_url, params=params)
if resp.status_code != 200:
raise Exception(f'Error get_arkstore_access_token: {resp.status_code}')
resp = resp.json()
return resp['access_token']


def get_arkstore_extensions(access_token, purchased=None):
arkstore_extensions_url = settings.ARKSTOER_URL + '/api/v1/arkstore/extensions'
headers = {'Authorization': f'Token {access_token}'}
params = {}
if purchased is not None:
params['purchased'] = purchased
resp = requests.get(arkstore_extensions_url, params=params, headers=headers).json()
return resp


def purcharse_arkstore_extension(access_token, extension_uuid):
order_url = settings.ARKSTOER_URL + '/api/v1/orders'
headers = {'Authorization': f'Token {access_token}'}
params = {
'extension_uuid': extension_uuid
}
resp = requests.post(order_url, json=params, headers=headers).json()
return resp


def download_arkstore_extension(access_token, extension_uuid):
import config
from pathlib import Path

ext_detail_url = settings.ARKSTOER_URL + f'/api/v1/arkstore/extensions/{extension_uuid}'
headers = {'Authorization': f'Token {access_token}'}
resp = requests.get(ext_detail_url, headers=headers)
if resp.status_code != 200:
return 'failed'
extension_name = resp.json()['name']

app_config = config.get_app_config()
extension_root = app_config.extension.root

download_url = settings.ARKSTOER_URL + f'/api/v1/arkstore/extensions/{extension_uuid}/download'
headers = {'Authorization': f'Token {access_token}'}
resp = requests.get(download_url, headers=headers)
if resp.status_code != 200:
return {'error': 'download failed'}

# delete extension folder
folder_name = Path(extension_root) / extension_name
import shutil
if folder_name.exists():
try:
shutil.rmtree(folder_name)
except OSError as e:
print ("Error remove folder: %s - %s." % (e.filename, e.strerror))
return {'error': 'delete extension fodler failed'}

# unzip
import zipfile
import io
extract_folder = Path(extension_root)
with zipfile.ZipFile(io.BytesIO(resp.content)) as zip_ref:
zip_ref.extractall(extract_folder)

return {'success': 'true'}
@extend_schema(roles=['globaladmin'], tags=['arkstore-extension'], summary='arkstore下单')
class ArkStoreBindAgentView(GenericAPIView):

permission_classes = [IsAuthenticated, ApiAccessPermission]
authentication_classes = [ExpiringTokenAuthentication]

def post(self, request, tenant_uuid, *args, **kwargs):
tenant_slug = request.data['tenant_slug']
token = request.user.token
tenant = Tenant.objects.get(uuid=tenant_uuid)
access_token = get_arkstore_access_token(tenant, token)
resp = bind_arkstore_agent(access_token, tenant_slug)
return JsonResponse(resp)


@extend_schema(roles=['globaladmin'], tags=['arkstore-extension'], summary='arkstore下单')
class ArkStoreGetAutoFormFillDataView(GenericAPIView):

permission_classes = [IsAuthenticated, ApiAccessPermission]
authentication_classes = [ExpiringTokenAuthentication]

def get(self, request, tenant_uuid, *args, **kwargs):
extension_uuid = kwargs['pk']
token = request.user.token
tenant = Tenant.objects.get(uuid=tenant_uuid)
result = get_arkid_saas_app_detail(tenant, token, extension_uuid)
return JsonResponse(result)
18 changes: 14 additions & 4 deletions api/v1/views/bind_saas.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from perm.custom_access import ApiAccessPermission
from oauth2_provider.models import Application
from api.v1.serializers.bind_saas import ArkIDBindSaasSerializer, ArkIDBindSaasCreateSerializer
from common.arkstore import create_tenant_oidc_app


@extend_schema(tags=["arkid"])
Expand Down Expand Up @@ -59,6 +60,8 @@ def post(self, request, tenant_uuid, *args, **kwargs):
'saas_tenant_uuid': resp['saas_tenant_uuid'],
'saas_tenant_slug': resp['saas_tenant_slug'],
}
self.create_arkidstore_login_app(tenant, resp['saas_tenant_slug'])
self.create_arkid_saas_login_app(tenant, resp['saas_tenant_slug'])
return Response(data, HTTP_200_OK)

@extend_schema(roles=['globaladmin'], request=ArkIDBindSaasSerializer, summary='查询saas绑定信息')
Expand All @@ -67,6 +70,9 @@ def get(self, request, tenant_uuid, *args, **kwarg):
查询 saas 绑定信息
"""
bind_info = self.get_bind_info(tenant_uuid)
tenant = Tenant.objects.get(uuid=tenant_uuid)
self.create_arkidstore_login_app(tenant, bind_info['saas_tenant_slug'])
self.create_arkid_saas_login_app(tenant, bind_info['saas_tenant_slug'])
return Response(bind_info, HTTP_200_OK)

@extend_schema(roles=['tenantadmin', 'globaladmin'], request=ArkIDBindSaasSerializer)
Expand All @@ -76,6 +82,8 @@ def patch(self, request, tenant_uuid, *args, **kwarg):
"""
tenant = Tenant.objects.get(uuid=tenant_uuid)
bind_info = self.update_saas_binding(tenant, request)
self.create_arkidstore_login_app(tenant, bind_info['saas_tenant_slug'])
self.create_arkid_saas_login_app(tenant, bind_info['saas_tenant_slug'])
return Response(bind_info, HTTP_200_OK)

def get_bind_info(self, tenant_uuid):
Expand Down Expand Up @@ -132,9 +140,11 @@ def update_saas_binding(self, tenant, request):
return resp

def create_arkidstore_login_app(self, tenant, saas_tenant_slug):
# url = f"{settings.ARKSTOER_URL.rstrip('/')}/api/v1/login?tenant_slug={resp['saas_tenant_slug']}"
pass
url = f"{settings.ARKSTOER_URL}/api/v1/login?tenant_slug={saas_tenant_slug}"
create_tenant_oidc_app(tenant, url, 'arkstore_login', 'arkidstore login')

def create_arkid_saas_login_app(self, tenant, saas_tenant_slug):
# url = settings.ARKID_SAAS
pass
arkid_saas_url = settings.ARKSTOER_URL
http, host = arkid_saas_url.split('://', 1)
url = f"{http}://{saas_tenant_slug}.{host}"
create_tenant_oidc_app(tenant, url, 'arkdi_saas_login', 'arkid_saas login')
Loading

0 comments on commit 4355fb0

Please sign in to comment.