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: added query display name for frontend #2047

Merged
merged 28 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7cc4bed
feat: added query display name for frontend
rolin999 Feb 12, 2025
b13e2d3
feat: added query display name for frontend
rolin999 Feb 12, 2025
5cbc3ad
feat: added query display name for frontend
rolin999 Feb 13, 2025
655ab27
feat: added query display name for frontend
rolin999 Feb 13, 2025
7405f2f
feat: added query display name for frontend
rolin999 Feb 13, 2025
d826328
feat: added query display name for frontend
rolin999 Feb 13, 2025
5c312ed
feat: added query display name for frontend
rolin999 Feb 13, 2025
6aac22a
feat: added query display name for frontend
rolin999 Feb 13, 2025
94af97e
feat: added query display name for frontend
rolin999 Feb 13, 2025
19e8432
feat: added query display name for frontend
rolin999 Feb 13, 2025
97c34ed
resolve: fix some problems
rolin999 Feb 18, 2025
a4135ce
resolve: fix some problems
rolin999 Feb 18, 2025
81b31a9
resolve: fix some problems
rolin999 Feb 18, 2025
1a4e6fe
resolve: fix some problems
rolin999 Feb 19, 2025
a3b9bd6
resolve: fix some problems
rolin999 Feb 19, 2025
85f940f
resolve: fix some problems
rolin999 Feb 19, 2025
82434d1
resolve: fix some problems
rolin999 Feb 19, 2025
5cc94bb
resolve: fix some problems
rolin999 Feb 19, 2025
8abe023
resolve: fix some problems
rolin999 Feb 19, 2025
70eb717
resolve: fix some problems
rolin999 Feb 19, 2025
08626b4
resolve: fix some problems
rolin999 Feb 21, 2025
cbe1cf9
resolve: fix some problems
rolin999 Feb 21, 2025
299d509
resolve: fix some problems
rolin999 Feb 24, 2025
3b7a53b
resolve: fix some problems
rolin999 Feb 24, 2025
c6216c4
resolve: fix some problems
rolin999 Feb 24, 2025
fd23281
resolve: fix some problems
rolin999 Feb 24, 2025
6b6a2e9
resolve: fix some problems
rolin999 Feb 24, 2025
51ef7b6
resolve: fix some problems
rolin999 Feb 24, 2025
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
6 changes: 5 additions & 1 deletion src/bk-user/bin/post_migrate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ set -e

# 自动化同步网关
if [ "$ENABLE_SYNC_APIGW" = true ]; then
sh ./support-files/bin/sync-apigateway.sh
sh ./support-files/bin/sync-bk-user-apigateway.sh
fi

if [ "$ENABLE_SYNC_WEB_APIGW" = true ]; then
sh ./support-files/bin/sync-bk-user-web-apigateway.sh
fi

# 注册到蓝鲸通知中心
Expand Down
2 changes: 1 addition & 1 deletion src/bk-user/bkuser/apis/open_v3/serializers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
class TenantUserDisplayNameListInputSLZ(serializers.Serializer):
bk_usernames = StringArrayField(
help_text="蓝鲸用户唯一标识,多个使用逗号分隔",
max_items=settings.BATCH_QUERY_USER_DISPLAY_NAME_BY_BK_USERNAME_LIMIT,
max_items=settings.BATCH_QUERY_USER_DISPLAY_INFO_BY_BK_USERNAME_LIMIT,
)


Expand Down
16 changes: 16 additions & 0 deletions src/bk-user/bkuser/apis/open_web/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - 用户管理 (bk-user) available.
# Copyright (C) 2017 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.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.
55 changes: 55 additions & 0 deletions src/bk-user/bkuser/apis/open_web/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - 用户管理 (bk-user) available.
# Copyright (C) 2017 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.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.

from functools import cached_property

from apigw_manager.drf.authentication import ApiGatewayJWTAuthentication
from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request

from bkuser.apps.data_source.constants import DataSourceTypeEnum
from bkuser.apps.data_source.models import DataSource


class OpenWebApiCommonMixin:
authentication_classes = [ApiGatewayJWTAuthentication]
permission_classes = [IsAuthenticated]

request: Request

TenantHeaderKey = "HTTP_X_BK_TENANT_ID"

@cached_property
def tenant_id(self) -> str:
tenant_id = self.request.META.get(self.TenantHeaderKey)

if not tenant_id:
raise ValidationError("X-Bk-Tenant-Id header is required")

return tenant_id

@cached_property
def real_data_source_id(self) -> int:
data_source = (
DataSource.objects.filter(owner_tenant_id=self.tenant_id, type=DataSourceTypeEnum.REAL).only("id").first()
)
if not data_source:
raise ValidationError(_("当前租户不存在实名用户数据源"))

return data_source.id
44 changes: 44 additions & 0 deletions src/bk-user/bkuser/apis/open_web/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - 用户管理 (bk-user) available.
# Copyright (C) 2017 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.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.
from django.conf import settings
from rest_framework import serializers

from bkuser.apps.tenant.models import TenantUser
from bkuser.biz.tenant import TenantUserHandler
from bkuser.common.serializers import StringArrayField


class TenantUserDisplayInfoRetrieveOutputSLZ(serializers.Serializer):
display_name = serializers.SerializerMethodField(help_text="用户展示名称")

def get_display_name(self, obj: TenantUser) -> str:
return TenantUserHandler.generate_tenant_user_display_name(obj)


class TenantUserDisplayInfoListInputSLZ(serializers.Serializer):
bk_usernames = StringArrayField(
help_text="蓝鲸用户唯一标识,多个使用逗号分隔",
max_items=settings.BATCH_QUERY_USER_DISPLAY_INFO_BY_BK_USERNAME_LIMIT,
)


class TenantUserDisplayInfoListOutputSLZ(serializers.Serializer):
bk_username = serializers.CharField(help_text="蓝鲸用户唯一标识", source="id")
display_name = serializers.SerializerMethodField(help_text="用户展示名称")

def get_display_name(self, obj: TenantUser) -> str:
return TenantUserHandler.generate_tenant_user_display_name(obj)
40 changes: 40 additions & 0 deletions src/bk-user/bkuser/apis/open_web/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - 用户管理 (bk-user) available.
# Copyright (C) 2017 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.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.

from django.urls import include, path

from . import views

urlpatterns = [
path(
"tenant/",
include(
[
path(
"users/-/display_info/",
views.TenantUserDisplayInfoListApi.as_view(),
name="open_web.tenant_user.display_info.list",
),
path(
"users/<str:id>/display_info/",
views.TenantUserDisplayInfoRetrieveApi.as_view(),
name="open_web.tenant_user.display_info.retrieve",
),
]
),
)
]
99 changes: 99 additions & 0 deletions src/bk-user/bkuser/apis/open_web/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - 用户管理 (bk-user) available.
# Copyright (C) 2017 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.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.

from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_control
from drf_yasg.utils import swagger_auto_schema
from rest_framework import generics, status
from rest_framework.response import Response

from bkuser.apis.open_web.mixins import OpenWebApiCommonMixin
from bkuser.apis.open_web.serializers import (
TenantUserDisplayInfoListInputSLZ,
TenantUserDisplayInfoListOutputSLZ,
TenantUserDisplayInfoRetrieveOutputSLZ,
)
from bkuser.apps.tenant.models import TenantUser
from bkuser.biz.tenant import TenantUserHandler


class TenantUserDisplayInfoRetrieveApi(OpenWebApiCommonMixin, generics.RetrieveAPIView):
"""
查询用户展示信息
Note: 前端服务专用 API 接口,该接口对性能要求较高,所以不进行序列化,且查询必须按字段
"""

@swagger_auto_schema(
tags=["open_web.user"],
operation_id="retrieve_user_display_info",
operation_description="查询用户展示信息",
responses={status.HTTP_200_OK: TenantUserDisplayInfoRetrieveOutputSLZ()},
)
@method_decorator(cache_control(public=True, max_age=60 * 5))
def get(self, request, *args, **kwargs):
# TODO: 由于目前 DisplayName 渲染只与 full_name 相关,所以只查询 full_name
# 后续支持表达式,则需要查询表达式可配置的所有字段
tenant_user = get_object_or_404(
TenantUser.objects.filter(
tenant_id=self.tenant_id,
data_source_id=self.real_data_source_id,
)
.select_related("data_source_user")
.only("data_source_user__full_name"),
id=kwargs["id"],
)

return Response({"display_name": TenantUserHandler.generate_tenant_user_display_name(tenant_user)})


class TenantUserDisplayInfoListApi(OpenWebApiCommonMixin, generics.ListAPIView):
"""
批量查询用户展示信息
Note: 前端服务专用 API 接口
"""

pagination_class = None

serializer_class = TenantUserDisplayInfoListOutputSLZ

def get_queryset(self):
slz = TenantUserDisplayInfoListInputSLZ(data=self.request.query_params)
slz.is_valid(raise_exception=True)
data = slz.validated_data

# TODO: 由于目前 DisplayName 渲染只与 full_name 相关,所以只查询 full_name
# 后续支持表达式,则需要查询表达式可配置的所有字段
return (
TenantUser.objects.filter(
id__in=data["bk_usernames"],
tenant_id=self.tenant_id,
data_source_id=self.real_data_source_id,
)
.select_related("data_source_user")
.only("id", "data_source_user__full_name")
)

@swagger_auto_schema(
tags=["open_web.user"],
operation_id="batch_query_user_display_info",
operation_description="批量查询用户展示信息",
query_serializer=TenantUserDisplayInfoListInputSLZ(),
responses={status.HTTP_200_OK: TenantUserDisplayInfoListOutputSLZ(many=True)},
)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
25 changes: 22 additions & 3 deletions src/bk-user/bkuser/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# to the current version of the project delivered to anyone in the future.

import hashlib
import re
from pathlib import Path
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
Expand Down Expand Up @@ -126,7 +127,10 @@
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

# Auth
AUTHENTICATION_BACKENDS = ["bkuser.auth.backends.TokenBackend"]
AUTHENTICATION_BACKENDS = [
"bkuser.auth.backends.TokenBackend",
"apigw_manager.apigw.authentication.UserModelBackend",
]
AUTH_USER_MODEL = "bkuser_auth.User"

# Internationalization
Expand Down Expand Up @@ -188,6 +192,7 @@

# bk_language domain
BK_DOMAIN = env.str("BK_DOMAIN", default="")
BK_DOMAIN_SCHEME = env.str("BK_DOMAIN_SCHEME", default="http")
# BK USER URL
BK_USER_URL = env.str("BK_USER_URL")
AJAX_BASE_URL = env.str("AJAX_BASE_URL", SITE_URL)
Expand Down Expand Up @@ -234,10 +239,24 @@
# bk apigw url tmpl
BK_API_URL_TMPL = env.str("BK_API_URL_TMPL")
BK_APIGW_NAME = env.str("BK_APIGW_NAME", default="bk-user")
# bk-user-web 网关跨域插件配置 allow_origins 和 allow_origins_by_regex
# Note: allow_origins 和 allow_origins_by_regex 必须二选一,不能同时填写,否则将导致网关注册失败
# 例如:BK_APIGW_CORS_ALLOW_ORIGINS=http://demo.example.com,https://demo.example.com
# BK_APIGW_CORS_ALLOW_ORIGINS_BY_REGEX=^http://.*\.example\.com$,^https://.*\.example\.com$
BK_APIGW_CORS_ALLOW_ORIGINS = env.str("BK_APIGW_CORS_ALLOW_ORIGINS", default="")
BK_APIGW_CORS_ALLOW_ORIGINS_BY_REGEX = env.list(
"BK_APIGW_CORS_ALLOW_ORIGINS_BY_REGEX",
default=[
rf"^{BK_DOMAIN_SCHEME}://.*\.{re.escape(BK_DOMAIN)}$",
rf"^{BK_DOMAIN_SCHEME}://{re.escape(BK_DOMAIN)}$",
],
)
# 与网关内部调用的认证 Token
BK_APIGW_TO_BK_USER_INNER_BEARER_TOKEN = env.str("BK_APIGW_TO_BK_USER_INNER_BEARER_TOKEN", default="")
# 是否自动同步网关
ENABLE_SYNC_APIGW = env.bool("ENABLE_SYNC_APIGW", default=False)
# 是否自动同步 Web 网关
ENABLE_SYNC_WEB_APIGW = env.bool("ENABLE_SYNC_WEB_APIGW", default=False)

# 版本日志
VERSION_LOG_FILES_DIR = BASE_DIR / "version_log"
Expand Down Expand Up @@ -683,5 +702,5 @@ def _build_file_handler(log_path: Path, filename: str, format: str) -> Dict:
# 限制批量操作数量上限,避免性能问题 / 误操作(目前不支持跨页全选,最大单页 100 条数据)
ORGANIZATION_BATCH_OPERATION_API_LIMIT = env.int("ORGANIZATION_BATCH_OPERATION_API_LIMIT", 100)

# 限制 bk_username 批量查询 display_name 的数量上限,避免性能问题
BATCH_QUERY_USER_DISPLAY_NAME_BY_BK_USERNAME_LIMIT = env.int("BATCH_QUERY_USER_DISPLAY_NAME_BY_BK_USERNAME_LIMIT", 100)
# 限制 bk_username 批量查询 display_info 的数量上限,避免性能问题
BATCH_QUERY_USER_DISPLAY_INFO_BY_BK_USERNAME_LIMIT = env.int("BATCH_QUERY_USER_DISPLAY_INFO_BY_BK_USERNAME_LIMIT", 100)
2 changes: 2 additions & 0 deletions src/bk-user/bkuser/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
path("api/v3/apigw/", include("bkuser.apis.apigw.urls")),
# 对外开放的 API
path("api/v3/open/", include("bkuser.apis.open_v3.urls")),
# 提供给前端使用的开放 API
path("api/v3/open-web/", include("bkuser.apis.open_web.urls")),
# 兼容旧版本用户管理 OpenAPI
# Q: 这里使用 api/v1、api/v2 而非 api/v1/open、api/v2/open
# A: 为了保证 ESB 调用的兼容,只需修改 ESB 配置 bk_user host,不需要依赖 ESB 的版本发布
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set -e
gateway_name="bk-user"

# 待同步网关、资源定义文件,需调整为实际的配置文件地址
definition_file="support-files/definition.yaml"
resources_file="support-files/resources.yaml"
definition_file="support-files/bk-user-apigateway/definition.yaml"
resources_file="support-files/bk-user-apigateway/resources.yaml"

echo "gateway sync definition start ..."

Expand Down
35 changes: 35 additions & 0 deletions src/bk-user/support-files/bin/sync-bk-user-web-apigateway.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

set -e

gateway_name="bk-user-web"

# 待同步网关、资源定义文件,需调整为实际的配置文件地址
definition_file="support-files/bk-user-web-apigateway/definition.yaml"
resources_file="support-files/bk-user-web-apigateway/resources.yaml"

echo "gateway sync definition start ..."

# 同步网关基本信息
echo "gateway sync definition start ..."
python manage.py sync_apigw_config --gateway-name=${gateway_name} --file="${definition_file}"

# 同步网关环境信息
python manage.py sync_apigw_stage --gateway-name=${gateway_name} --file="${definition_file}"

# 同步网关资源
python manage.py sync_apigw_resources --delete --gateway-name=${gateway_name} --file="${resources_file}"

# 同步资源文档
python manage.py sync_resource_docs_by_archive --gateway-name=${gateway_name} --file="${definition_file}"

# 创建资源版本、发布
python manage.py create_version_and_release_apigw --gateway-name=${gateway_name} --file="${definition_file}"

## 为应用主动授权
#python manage.py grant_apigw_permissions --gateway-name=${gateway_name} --file="${definition_file}"

# 获取网关公钥
python manage.py fetch_apigw_public_key --gateway-name=${gateway_name}

echo "gateway sync definition end"
Loading