Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 发版 #870

Merged
merged 15 commits into from
May 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions api/v1/pages/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,49 @@
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/',
'method': 'get'
},
'global': {
'bind_agent': {
'tag': 'bind_agent',
'description': '绑定代理商',
}
},
'local': {
'purchase': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/order/',
'method': 'post',
'description': '购买'
},
'download': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/download/{id}/',
'install': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/install/{id}/',
'method': 'get',
'description': '安装'
},
'upgrade': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/install/{id}/',
'method': 'get',
'description': '下载'
'description': '升级'
}
}
}
)

bind_agent_tag = 'bind_agent'
bind_agent_name = '绑定代理商'

extend_schema_tags(
bind_agent_tag,
bind_agent_name,
{
'type': 'form_page',
'init': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/bind_agent/',
'method': 'get',
},
'global': {
'update': {
'path': '/api/v1/tenant/{tenant_uuid}/arkstore/bind_agent/',
'method': 'post',
'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',
),
]
1 change: 1 addition & 0 deletions api/v1/urls/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@

urlpatterns = [
path('get_frontendurl/', views_setup.GetFrontendUrlAPIView.as_view(), name='get-frontendurl'),
path('set_frontendurl/', views_setup.SetFrontendUrlAPIView.as_view(), name='set-frontendurl'),
]
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