Skip to content

Commit

Permalink
Merge pull request #1216 from longguikeji/release-2.5.7
Browse files Browse the repository at this point in the history
Release 2.5.7
  • Loading branch information
notevery committed Aug 29, 2022
2 parents 827fe40 + 90144d3 commit b1b5635
Show file tree
Hide file tree
Showing 27 changed files with 342 additions and 65 deletions.
6 changes: 6 additions & 0 deletions api/v1/pages/desktop/mine_app_group_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@
path='/api/v1/mine/tenant/{tenant_id}/mine_group_apps/?app_group_id={app_group_id}',
method=actions.FrontActionMethod.GET
),
node_actions=[
actions.DirectAction(
path='/api/v1/tenant/{tenant_id}/arkstore/apps/{id}/click/',
method=actions.FrontActionMethod.GET,
)
],
)
4 changes: 2 additions & 2 deletions api/v1/pages/mine/auth_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

mine_accounts_bind_page.create_actions(
init_action=actions.DirectAction(
path='/api/v1/mine/tenant/{tenant_id}/accounts/?show_type=unbind',
path='/api/v1/mine/tenant/{tenant_id}/unbind_accounts/',
method=actions.FrontActionMethod.GET,
),
local_actions={
Expand All @@ -24,7 +24,7 @@

mine_accounts_unbind_page.create_actions(
init_action=actions.DirectAction(
path='/api/v1/mine/tenant/{tenant_id}/accounts/?show_type=bind',
path='/api/v1/mine/tenant/{tenant_id}/accounts/',
method=actions.FrontActionMethod.GET,
),
local_actions={
Expand Down
14 changes: 13 additions & 1 deletion api/v1/schema/mine.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,19 @@ class MineBindAccountItem(Schema):

id: UUID
name: str = Field(default='', title=_('名称'))
nickname: str = Field(default='', title=_('昵称'))
avatar: str = Field(default='', title=_('头像'))


class MineBindAccountOut(ResponseSchema):
data:List[MineBindAccountItem]
data:List[MineBindAccountItem]


class MineUnBindAccountItem(Schema):

id: UUID
name: str = Field(default='', title=_('名称'))


class MineUnBindAccountOut(ResponseSchema):
data:List[MineUnBindAccountItem]
4 changes: 2 additions & 2 deletions api/v1/views/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


@api.get("/tenant/{tenant_id}/apps/", response=List[AppListItemOut], tags=['应用'])
@operation(AppListOut, roles=[TENANT_ADMIN, PLATFORM_ADMIN])
@operation(AppListOut, roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN])
@paginate(CustomPagination)
def list_apps(request, tenant_id: str):
'''
Expand Down Expand Up @@ -109,7 +109,7 @@ def get_app(request, tenant_id: str, id: str):
return {"data":app}

@api.get("/tenant/{tenant_id}/apps/{app_id}/openapi_version/", response=ConfigOpenApiVersionDataSchemaOut, tags=['应用'])
@operation(roles=[TENANT_ADMIN, PLATFORM_ADMIN, NORMAL_USER])
@operation(roles=[PLATFORM_ADMIN, NORMAL_USER])
def get_app_openapi_version(request, tenant_id: str, app_id: str):
'''
获取app的openapi地址和版本
Expand Down
2 changes: 1 addition & 1 deletion api/v1/views/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def get_arkstore_list(request, purchased, type, rented=False, all=False, extra_p
page_size = request.GET.get('page_size', 10)
token = request.user.auth_token
tenant = request.tenant
access_token = get_arkstore_access_token(tenant, token.token)
access_token = get_arkstore_access_token(tenant, token)
# arkstore use offset and limit
if page and page_size:
limit = int(page_size)
Expand Down
2 changes: 1 addition & 1 deletion api/v1/views/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def list_extensions(request, status: str = None):
return qs

token = request.user.auth_token
access_token = get_arkstore_access_token(tenant, token)
# access_token = get_arkstore_access_token(tenant, token)
# resp = get_arkstore_extensions_purchased(access_token)
resp = get_arkstore_list(request, True, 'extension', all=True)['items']
extensions_purchased = {ext['package']: ext for ext in resp}
Expand Down
67 changes: 60 additions & 7 deletions api/v1/views/mine.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
from arkid.core.error import ErrorCode, ErrorDict, SuccessDict
from arkid.core.translation import gettext_default as _
from arkid.core.pagenation import CustomPagination
from arkid.core.event import ACCOUNT_UNBIND, dispatch_event, Event
from arkid.core.models import App, AppGroup, Message, Tenant, ApproveRequest, User
from arkid.core.constants import NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from ninja.pagination import paginate
from django.db.models import Q
from ..schema.mine import *
Expand Down Expand Up @@ -189,7 +191,7 @@ def get_mine_tenants(request):
@api.get("/mine/tenant/{tenant_id}/accounts/", tags=["我的"], response=List[MineBindAccountItem])
@operation(MineBindAccountOut,roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN])
@paginate(CustomPagination)
def get_mine_accounts(request, tenant_id: str, show_type:str = 'bind'):
def get_mine_accounts(request, tenant_id: str):
"""我的绑定账号"""
from arkid.core.expand import field_expand_map
from arkid.extension.models import Extension as ExtensionModel
Expand All @@ -202,6 +204,7 @@ def get_mine_accounts(request, tenant_id: str, show_type:str = 'bind'):
qs_dict[str(item.package).replace('.','_')] = item
# 筛选出用户所拥有的插件
table_name = User._meta.db_table
add_package_record = []
items = []
if table_name in field_expand_map:
field_expands = field_expand_map.get(table_name,{})
Expand All @@ -210,20 +213,62 @@ def get_mine_accounts(request, tenant_id: str, show_type:str = 'bind'):
verbose_name = field_item.verbose_name
field_name = field_item.name
if field_name == field:
if extension_name in qs_dict and field_name in user_expand:
if extension_name in qs_dict and field_name in user_expand and extension_name not in add_package_record:
user_filter_value = user_expand.get(field_name, None)
if user_filter_value and show_type == 'bind':
if user_filter_value:
qs_item = qs_dict.get(extension_name)
first_field_name = field_name.replace("user_id", "")
nickname_field_name = first_field_name+'nickname'
avatar_field_name = first_field_name+'avatar'
items.append({
'id': qs_item.id,
'name': qs_item.name
'name': qs_item.name,
'nickname': user_expand.get(nickname_field_name, ''),
'avatar': user_expand.get(avatar_field_name, '')
# 'nickname': qs_item.nickname,
# 'avatar': qs_item.avatar
})
elif (user_filter_value is None or user_filter_value == '') and show_type == 'unbind':
add_package_record.append(extension_name)
break
return items


@api.get("/mine/tenant/{tenant_id}/unbind_accounts/", tags=["我的"], response=List[MineUnBindAccountItem])
@operation(MineUnBindAccountOut,roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN])
@paginate(CustomPagination)
def get_mine_unbind_accounts(request, tenant_id: str):
"""我的没绑定账户"""
from arkid.core.expand import field_expand_map
from arkid.extension.models import Extension as ExtensionModel
user_expand = request.user_expand
# 梳理出登录类型的插件
qs = ExtensionModel.valid_objects.all()
qs_dict = {}
exclude_packages = ['com.longgui.external.idp.miniprogram']
for item in qs:
if item.type == 'external_idp' and item.package not in exclude_packages:
qs_dict[str(item.package).replace('.','_')] = item
# 筛选出用户所拥有的插件
table_name = User._meta.db_table
items = []
add_package_record = []
if table_name in field_expand_map:
field_expands = field_expand_map.get(table_name,{})
for table, field,extension_name,extension_model_cls,extension_table,extension_field in field_expands:
for field_item in extension_model_cls._meta.fields:
verbose_name = field_item.verbose_name
field_name = field_item.name
if field_name == field:
if extension_name in qs_dict and field_name in user_expand and extension_name not in add_package_record:

user_filter_value = user_expand.get(field_name, None)
if user_filter_value is None or user_filter_value == '':
qs_item = qs_dict.get(extension_name)
items.append({
'id': qs_item.id,
'name': qs_item.name
})
add_package_record.append(extension_name)
break
return items

Expand Down Expand Up @@ -260,6 +305,12 @@ def unbind_mine_account(request, tenant_id: str, account_id: str):
extension_model_cls.valid_objects.filter(
target=user
).delete()
# 发送取消绑定事件
select_package = select_package.replace('_','.')
data = {
'user_id': str(request.user.id)
}
dispatch_event(Event(tag=ACCOUNT_UNBIND, tenant=request.tenant, request=request, data=data, packages=[select_package]))
break
return ErrorDict(ErrorCode.OK)

Expand Down Expand Up @@ -288,8 +339,10 @@ def bind_mine_account(request, tenant_id: str, account_id: str):
f'api:{select_package}:{select_package}_login',
args=[config_created.id],
)
login_url = login_url + '?next={}/mine_auth_manage'.format(front_host)
return HttpResponseRedirect(login_url)
login_url = login_url + '?next={}/mine/mine_auth_manage'.format(front_host)
return {
"redirect":login_url
}
else:
return ErrorDict(ErrorCode.PLUG_IN_NOT_START)

Expand Down
24 changes: 17 additions & 7 deletions arkid/common/arkstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_saas_token(tenant, token, use_cache=True):
获取saas平台token
"""
# 缓存 saas_token
key = (str(tenant.id), token)
key = (str(tenant.id) + '_' + str(token)).replace('-', '')
if use_cache and key in arkid_saas_token_cache:
return arkid_saas_token_cache[key]
app = Application.objects.filter(name='arkid_saas', uuid = tenant.id).first()
Expand Down Expand Up @@ -66,9 +66,15 @@ def get_arkstore_access_token(tenant, token, use_cache=True):
"""
获取插件商店access_token
"""
saas_token, saas_tenant_id, saas_tenant_slug = get_saas_token(tenant, token, use_cache=use_cache)
return get_arkstore_access_token_with_saas_token(saas_tenant_slug, saas_tenant_id, saas_token,
use_cache=use_cache, local_tenant=tenant, local_token=token)
try:
saas_token, saas_tenant_id, saas_tenant_slug = get_saas_token(tenant, token, use_cache=use_cache)
return get_arkstore_access_token_with_saas_token(saas_tenant_slug, saas_tenant_id, saas_token,
use_cache=use_cache, local_tenant=tenant, local_token=token)
except Exception as e:
logger.error(f'get_arkstore_access_token failed: {str(e)}, give it a retry')
saas_token, saas_tenant_id, saas_tenant_slug = get_saas_token(tenant, token, use_cache=False)
return get_arkstore_access_token_with_saas_token(saas_tenant_slug, saas_tenant_id, saas_token,
use_cache=False, local_tenant=tenant, local_token=token)


arkstore_access_token_saas_cache = {}
Expand All @@ -79,7 +85,7 @@ def get_arkstore_access_token_with_saas_token(saas_tenant_slug, saas_tenant_id,
获取插件商店access_token
"""
# 缓存 idtoken
key = (str(saas_tenant_id), saas_token)
key = (str(saas_tenant_id) + '_' + str(saas_token)).replace('-', '')
if use_cache and key in arkstore_access_token_saas_cache:
try:
payload = jwt.decode(arkstore_access_token_saas_cache[key], options={"verify_signature": False})
Expand All @@ -102,8 +108,12 @@ def get_arkstore_access_token_with_saas_token(saas_tenant_slug, saas_tenant_id,
resp = requests.get(app_login_url, params=params)
if resp.status_code != 200:
arkstore_access_token_saas_cache.pop(key, None)
raise Exception(f'Error get_arkstore_access_token_with_saas_token: {resp.status_code}')
resp = resp.json()
raise Exception(f'Error get_arkstore_access_token_with_saas_token: {resp.status_code}, url: {resp.url}')
try:
resp = resp.json()
except:
from urllib.parse import urlencode, unquote
raise Exception(f'Error get_arkstore_access_token_with_saas_token: {resp.status_code}, url: {unquote(resp.url)}')
arkstore_access_token_saas_cache[key] = resp['access_token']
return arkstore_access_token_saas_cache[key]

Expand Down
3 changes: 2 additions & 1 deletion arkid/core/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ def unlisten_event(tag, func, **kwargs):

AUTHRULE_FIX_LOGIN_PAGE = 'AUTHRULE_FIX_LOGIN_PAGE'
AUTHRULE_CHECK_AUTH_DATA = 'AUTHRULE_CHECK_AUTH_DATA'
ACCOUNT_UNBIND = 'ACCOUNT_UNBIND'

SET_FRONTEND_URL = 'SET_FRONTEND_URL'

Expand Down Expand Up @@ -440,7 +441,7 @@ def unlisten_event(tag, func, **kwargs):
register_event(READ_FILE, _('READ_FILE', '读取文件'))
register_event(ACCOUNT_LIFE_PERIODIC_TASK, _('ACCOUNT_LIFE_PERIODIC_TASK', '生命周期定时任务'))
register_event(CREATE_APPROVE_REQUEST, _('CREATE_APPROVE_REQUEST', '创建审批请求'))

register_event(ACCOUNT_UNBIND, _('ACCOUNT UNBIND'), '账户解绑')
register_event(AUTHFACTOR_CREATE_LOGIN_PAGE, _('AUTHFACTOR_CREATE_LOGIN_PAGE', '认证因素:创建登陆页面'))

register_event(AUTHRULE_FIX_LOGIN_PAGE, _('AUTHRULE_FIX_LOGIN_PAGE', '认证规则:填充登录页面'))
Expand Down
54 changes: 49 additions & 5 deletions arkid/core/extension/external_idp.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ def load(self):
self.listen_event(
core_event.CREATE_LOGIN_PAGE_AUTH_FACTOR, self.add_idp_login_buttons
)
self.listen_event(
core_event.ACCOUNT_UNBIND, self.account_unbind
)
super().load()

@abstractmethod
Expand Down Expand Up @@ -135,15 +138,24 @@ def get_arkid_user(self, ext_id):
"""
pass

def get_arkid_token(self, ext_id, config):
def get_arkid_token(self, ext_id, ext_name, ext_icon, config):
arkid_user = self.get_arkid_user(ext_id)
if arkid_user:
token = refresh_token(arkid_user)
from arkid.core.models import ExpiringToken
et = ExpiringToken.objects.filter(
user=arkid_user
).first()
if et and et.expired(config.tenant) is False:
token = et.token
else:
token = refresh_token(arkid_user)
context = {"token": token}
else:
context = {
"token": "",
"ext_id": ext_id,
"ext_name": ext_name,
"ext_icon": ext_icon,
"tenant_id": config.tenant.id.hex,
"bind": config.config.get('bind_url'),
}
Expand Down Expand Up @@ -197,7 +209,7 @@ def callback(self, request, config_id):
else:
return JsonResponse({"error_msg": "授权码丢失", "code": ["required"]})

context = self.get_arkid_token(ext_id, config)
context = self.get_arkid_token(ext_id, ext_name, ext_icon, config)
query_string = urlencode(context)
if next_url:
url = f"{next_url}?{query_string}"
Expand All @@ -211,11 +223,12 @@ def callback(self, request, config_id):
return HttpResponseRedirect(url)

@abstractmethod
def bind_arkid_user(self, ext_id, user):
def bind_arkid_user(self, ext_id, user, data):
"""
Args:
ext_id (str): 第三方登录返回的用户标识
user (arkid.core.models.User): ArkID的用户
data (dict) request数据
Returns:
{"token":xxx}: 返回token
"""
Expand All @@ -226,11 +239,31 @@ def bind(self, request, config_id):
"""
处理第三方身份源返回的user_id和ArkID的user之间的绑定
"""
from urllib.parse import unquote
from arkid.core.event import SAVE_FILE, dispatch_event, Event
from arkid.extension.models import Extension

ext_id = request.POST.get("ext_id")
user = verify_token(request)
if not user:
return JsonResponse({"error_msg": "Token验证失败", "code": ["token invalid"]})
self.bind_arkid_user(ext_id, user)
ext_icon = request.POST.get('ext_icon', '')
ext_name = request.POST.get('ext_name', '')
config = self.get_config_by_id(config_id)
extension = Extension.active_objects.filter(
type="storage"
).first()
if ext_name:
ext_name = unquote(ext_name)
request.POST['ext_name'] = ext_name
if ext_icon:
data = {
'fileurl': ext_icon
}
responses = dispatch_event(Event(tag=SAVE_FILE, tenant=config.tenant, request=request, packages=extension.package, data=data))
useless, (fileinfo, extension) = responses[0]
request.POST['ext_icon'] = fileinfo
self.bind_arkid_user(ext_id, user, request.POST)
# token = refresh_token(user)
# data = {"token": token}
data = {}
Expand Down Expand Up @@ -311,6 +344,17 @@ def add_idp_login_buttons(self, event, **kwargs):

logger.info(f'{self.package} add idp login buttions end')
return data

def account_unbind(self, event, **kwargs):
'''
在账户解绑的时候会调用此方法,开发者可以根据需要重写此方法
Params:
event: 事件参数
data: 数据
user_id: 用户id
'''
data = event.data
pass

@abstractmethod
def get_img_and_redirect_url(self, config):
Expand Down
Loading

0 comments on commit b1b5635

Please sign in to comment.