diff --git a/release.md b/release.md index 95dfd9b68..48b095404 100644 --- a/release.md +++ b/release.md @@ -1,3 +1,8 @@ +# V1.5.7 + +* 修复url拼接多个/导致访问出错问题 +* 修复前端人员列表组件范围地址错误问题 + # V1.5.6 ### 缺陷修复 diff --git a/saas/VERSION b/saas/VERSION index eac1e0ada..f01291b87 100644 --- a/saas/VERSION +++ b/saas/VERSION @@ -1 +1 @@ -1.5.6 +1.5.7 diff --git a/saas/backend/api/application/views.py b/saas/backend/api/application/views.py index 9670329cd..63b685ef1 100644 --- a/saas/backend/api/application/views.py +++ b/saas/backend/api/application/views.py @@ -22,6 +22,7 @@ from backend.biz.open import ApplicationPolicyListCache from backend.common.swagger import ResponseSwaggerAutoSchema from backend.trans.open_application import AccessSystemApplicationTrans +from backend.util.url import url_join from .serializers import AccessSystemApplicationSLZ, AccessSystemApplicationUrlSLZ @@ -59,7 +60,7 @@ def post(self, request): cache_id = self.application_policy_list_cache.set(policy_list) # 返回重定向地址 - url = f"{settings.APP_URL}/apply-custom-perm" + url = url_join(settings.APP_URL, "/apply-custom-perm") params = {"system_id": system_id, "cache_id": cache_id} url = url + "?" + urlencode(params) diff --git a/saas/backend/apps/role/tasks.py b/saas/backend/apps/role/tasks.py index c580c15db..4778266fd 100644 --- a/saas/backend/apps/role/tasks.py +++ b/saas/backend/apps/role/tasks.py @@ -23,6 +23,7 @@ from backend.common.time import get_soon_expire_ts from backend.component import esb from backend.service.constants import RoleRelatedObjectType, RoleType +from backend.util.url import url_join logger = logging.getLogger("celery") @@ -63,7 +64,7 @@ def role_group_expire_remind(): """ group_biz = GroupBiz() - base_url = f"{settings.APP_URL}/group-perm-renewal" + base_url = url_join(settings.APP_URL, "/group-perm-renewal") expired_at = get_soon_expire_ts() qs = Role.objects.all() diff --git a/saas/backend/apps/user/tasks.py b/saas/backend/apps/user/tasks.py index dde1ec568..82a2f2c7f 100644 --- a/saas/backend/apps/user/tasks.py +++ b/saas/backend/apps/user/tasks.py @@ -26,6 +26,7 @@ from backend.component import esb from backend.service.constants import SubjectType from backend.service.models import Subject +from backend.util.url import url_join logger = logging.getLogger("celery") @@ -42,7 +43,7 @@ def user_group_policy_expire_remind(): qs = User.objects.filter(staff_status=StaffStatus.IN.value) paginator = Paginator(qs, 100) - base_url = f"{settings.APP_URL}/perm-renewal" + base_url = url_join(settings.APP_URL, "/perm-renewal") if not paginator.count: return diff --git a/saas/backend/component/engine.py b/saas/backend/component/engine.py index 32f280914..0f141ce1e 100644 --- a/saas/backend/component/engine.py +++ b/saas/backend/component/engine.py @@ -15,6 +15,7 @@ from backend.common.error_codes import error_codes from backend.common.local import local from backend.util.json import json_dumps +from backend.util.url import url_join from .http import http_post, logger @@ -36,9 +37,9 @@ def _call_engine_api(http_func, url_path, data, timeout=30): if settings.BK_IAM_ENGINE_HOST_TYPE == "direct": headers.update({"X-Bk-App-Code": settings.APP_ID, "X-Bk-App-Secret": settings.APP_TOKEN}) - url = f"{settings.BK_IAM_ENGINE_HOST}/api/v1/engine{url_path}" + url = url_join(settings.BK_IAM_ENGINE_HOST, f"/api/v1/engine{url_path}") if settings.BK_IAM_ENGINE_HOST_TYPE == "direct": - url = f"{settings.BK_IAM_ENGINE_HOST}/api/v1{url_path}" + url = url_join(settings.BK_IAM_ENGINE_HOST, f"/api/v1{url_path}") kwargs = {"url": url, "data": data, "headers": headers, "timeout": timeout} ok, data = http_func(**kwargs) diff --git a/saas/backend/component/esb.py b/saas/backend/component/esb.py index a71770810..900168835 100644 --- a/saas/backend/component/esb.py +++ b/saas/backend/component/esb.py @@ -14,6 +14,7 @@ from backend.common.error_codes import error_codes from backend.common.local import local +from backend.util.url import url_join from .http import http_get, http_post, logger @@ -35,7 +36,7 @@ def _call_esb_api(http_func, url_path, data, timeout=30): } data.update(common_params) - url = f"{settings.BK_COMPONENT_API_URL}{url_path}" + url = url_join(settings.BK_COMPONENT_INNER_API_URL, url_path) kwargs = {"url": url, "data": data, "headers": headers, "timeout": timeout} ok, data = http_func(**kwargs) diff --git a/saas/backend/component/iam.py b/saas/backend/component/iam.py index 0e3a60e4a..820ec841d 100644 --- a/saas/backend/component/iam.py +++ b/saas/backend/component/iam.py @@ -17,6 +17,7 @@ from backend.common.local import local from backend.publisher import shortcut as publisher_shortcut from backend.util.cache import region +from backend.util.url import url_join from .http import http_delete, http_get, http_post, http_put, logger from .util import execute_all_data_by_paging, list_all_data_by_paging @@ -36,7 +37,7 @@ def _call_iam_api(http_func, url_path, data, timeout=30): "X-BK-APP-SECRET": settings.APP_TOKEN, "X-Request-Id": local.request_id, } - url = f"{settings.BK_IAM_HOST}{url_path}" + url = url_join(settings.BK_IAM_HOST, url_path) kwargs = {"url": url, "data": data, "headers": headers, "timeout": timeout} ok, data = http_func(**kwargs) diff --git a/saas/backend/healthz/views.py b/saas/backend/healthz/views.py index 9083c9b03..64ea46a06 100644 --- a/saas/backend/healthz/views.py +++ b/saas/backend/healthz/views.py @@ -17,6 +17,7 @@ from rest_framework import serializers from backend.component import usermgr +from backend.util.url import url_join logger = getLogger("app") @@ -114,7 +115,7 @@ def celery(self): def iam(self): try: - url = f"{settings.BK_IAM_HOST}/healthz" + url = url_join(settings.BK_IAM_HOST, "/healthz") resp = requests.get(url) if resp.status_code != requests.codes.ok: return False, f"iam backend response status[{resp.status_code}] not OK" diff --git a/saas/backend/service/application.py b/saas/backend/service/application.py index b9a48644a..7840333ab 100644 --- a/saas/backend/service/application.py +++ b/saas/backend/service/application.py @@ -17,6 +17,7 @@ from backend.plugins.application_ticket.base import ApplicationTicketProvider from backend.plugins.application_ticket.itsm import ITSMApplicationTicketProvider from backend.util.json import json_dumps +from backend.util.url import url_join from backend.util.uuid import gen_uuid from .models import ( @@ -51,7 +52,7 @@ def provider(self) -> ApplicationTicketProvider: def _generate_callback_info(self) -> Tuple[str, str]: """生成回调信息""" callback_id = gen_uuid() - callback_url = f"{settings.APP_API_URL}/api/v1/applications/{callback_id}/approve/" + callback_url = url_join(settings.APP_API_URL, f"/api/v1/applications/{callback_id}/approve/") return callback_id, callback_url def _create(self, data: TypeUnionApplicationData, create_ticket_func: Callable[[str], str]) -> Application: diff --git a/saas/backend/service/resource.py b/saas/backend/service/resource.py index f15085943..5fef5b96b 100644 --- a/saas/backend/service/resource.py +++ b/saas/backend/service/resource.py @@ -17,6 +17,7 @@ from backend.service.models.resource import ResourceApproverAttribute from backend.util.basic import chunked from backend.util.cache import redis_region, region +from backend.util.url import url_join from .models import ( ResourceAttribute, @@ -144,7 +145,7 @@ def __init__(self, system_id: str, resource_type_id: str): # 根据系统和资源类型获取相关认证信息和Host、URL_PATH provider_config = ResourceProviderConfig(system_id, resource_type_id) auth_info, host, url_path = provider_config.auth_info, provider_config.host, provider_config.path - url = f"{host}{url_path}" + url = url_join(host, url_path) self.client = resource_provider.ResourceProviderClient(system_id, resource_type_id, url, auth_info) # 缓存服务 self.id_name_cache = ResourceIDNameCache(system_id, resource_type_id) diff --git a/saas/backend/util/url.py b/saas/backend/util/url.py new file mode 100644 index 000000000..d66ebe6e1 --- /dev/null +++ b/saas/backend/util/url.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-权限中心(BlueKing-IAM) available. +Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + + +def url_join(host: str, path: str) -> str: + """ + 拼接host, path生成url + + 处理host, path有多余/的情况 + """ + return "{}/{}".format(host.rstrip("/"), path.lstrip("/")) diff --git a/saas/blueking/component/conf.py b/saas/blueking/component/conf.py index 36d50b0af..034343798 100644 --- a/saas/blueking/component/conf.py +++ b/saas/blueking/component/conf.py @@ -16,7 +16,7 @@ APP_CODE = settings.APP_ID SECRET_KEY = settings.APP_TOKEN - COMPONENT_SYSTEM_HOST = getattr(settings, 'BK_COMPONENT_API_URL', + COMPONENT_SYSTEM_HOST = getattr(settings, 'BK_COMPONENT_INNER_API_URL', settings.BK_PAAS_HOST) DEFAULT_BK_API_VER = getattr(settings, 'DEFAULT_BK_API_VER', 'v2') except Exception: # pylint: disable=broad-except diff --git a/saas/config/dev.py b/saas/config/dev.py index fdad1fd93..08aa2ab24 100644 --- a/saas/config/dev.py +++ b/saas/config/dev.py @@ -67,6 +67,8 @@ BK_PAAS_HOST = os.environ.get("BK_PAAS_HOST", BK_PAAS_HOST) BK_PAAS_INNER_HOST = os.environ.get("BK_PAAS_INNER_HOST", BK_PAAS_HOST) BK_IAM_HOST = "" +BK_COMPONENT_INNER_API_URL = BK_PAAS_INNER_HOST +BK_COMPONENT_API_URL = BK_PAAS_HOST # for vue LOGIN_SERVICE_URL = BK_PAAS_HOST.rstrip("/") + "/login/" diff --git a/saas/config/prod.py b/saas/config/prod.py index 02233b9d9..d719bbfa2 100644 --- a/saas/config/prod.py +++ b/saas/config/prod.py @@ -49,6 +49,7 @@ def get_app_service_url(app_code: str) -> str: SECRET_KEY = APP_TOKEN = os.environ.get("BKPAAS_APP_SECRET", SECRET_KEY) BK_PAAS_INNER_HOST = os.environ.get("BK_PAAS2_URL", BK_PAAS_INNER_HOST) BK_COMPONENT_API_URL = os.environ.get("BK_COMPONENT_API_URL") + BK_COMPONENT_INNER_API_URL = BK_COMPONENT_API_URL # 正式环境数据库可以在这里配置 DATABASES.update( # 需要兼容V3环境变量 @@ -89,7 +90,8 @@ def get_app_service_url(app_code: str) -> str: # V2 Smart 配置 else: - BK_COMPONENT_API_URL = BK_PAAS_INNER_HOST + BK_COMPONENT_INNER_API_URL = BK_PAAS_INNER_HOST + BK_COMPONENT_API_URL = BK_PAAS_HOST # 正式环境数据库可以在这里配置 DATABASES.update( diff --git a/saas/resources/version_log/V1.5.7_2021-10-11.md b/saas/resources/version_log/V1.5.7_2021-10-11.md new file mode 100644 index 000000000..1de771416 --- /dev/null +++ b/saas/resources/version_log/V1.5.7_2021-10-11.md @@ -0,0 +1,5 @@ +# V1.5.7 版本更新日志 + +### 缺陷修复 +* 修复url拼接多个/导致访问出错问题 +* 修复前端人员列表组件范围地址错误问题 diff --git a/saas/resources/version_log/V1.5.7_2021-10-11_en.md b/saas/resources/version_log/V1.5.7_2021-10-11_en.md new file mode 100644 index 000000000..fc9c56c82 --- /dev/null +++ b/saas/resources/version_log/V1.5.7_2021-10-11_en.md @@ -0,0 +1,5 @@ +# V1.5.7 ChangeLog + +### Bug Fixes +* Fix the problem of multiple url splicing/causing access errors +* Fix the problem of the wrong address of the front-end personnel list component range diff --git a/saas/tests/util/url_tests.py b/saas/tests/util/url_tests.py new file mode 100644 index 000000000..713b873b3 --- /dev/null +++ b/saas/tests/util/url_tests.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-权限中心(BlueKing-IAM) available. +Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import pytest + +from backend.util.url import url_join + + +@pytest.mark.parametrize( + "host, path, expected", + [ + ("http://host", "path", "http://host/path"), + ("http://host/", "path", "http://host/path"), + ("http://host", "/path", "http://host/path"), + ("http://host/", "/path", "http://host/path"), + ], +) +def test_url_join(host: str, path: str, expected: str): + assert url_join(host, path) == expected