Skip to content

Commit

Permalink
refactor: cr 调整
Browse files Browse the repository at this point in the history
cr调整
  • Loading branch information
neronkl committed Aug 22, 2023
1 parent 3aa77de commit 7fc371c
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 201 deletions.
43 changes: 43 additions & 0 deletions src/bk-user/bkuser/apis/web/organization/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) 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 logging

from django.conf import settings
from drf_yasg.utils import swagger_serializer_method
from rest_framework import serializers

from bkuser.apps.tenant.models import Tenant

logger = logging.getLogger(__name__)


class TenantDepartmentOutputSLZ(serializers.Serializer):
id = serializers.IntegerField(help_text="租户部门ID")
name = serializers.CharField(help_text="部门名称")
has_children = serializers.BooleanField(help_text="是否有子部门")


class TenantListOutputSLZ(serializers.Serializer):
id = serializers.CharField(help_text="租户ID")
name = serializers.CharField(help_text="租户名称")
logo = serializers.SerializerMethodField(help_text="租户 Logo")
departments = serializers.SerializerMethodField(help_text="租户下每个数据源的根组织")

def get_logo(self, instance: Tenant) -> str:
return instance.logo or settings.DEFAULT_TENANT_LOGO

@swagger_serializer_method(serializer_or_field=TenantDepartmentOutputSLZ(many=True))
def get_departments(self, instance: Tenant):
departments = self.context["tenant_root_departments_map"].get(instance.id)
# 可能存在了授权了数据源,但是一个根部门都未授权的情况存在
if not departments:
return []
return [item.model_dump(include={"id", "name", "has_children"}) for item in departments]
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@

urlpatterns = [
# 租户
path("tenants/", views.TenantsListApi.as_view(), name="tenant_departments.retrieve_tenant"),
path("tenants/<str:id>/", views.TenantRetrieveUpdateApi.as_view(), name="tenant_departments.retrieve_tenant"),
path("tenants/", views.TenantListApi.as_view(), name="organization.tenant.list"),
path("tenants/<str:id>/", views.TenantRetrieveUpdateApi.as_view(), name="organization.tenant.retrieve_update"),
]
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,39 @@
from rest_framework import generics, status
from rest_framework.response import Response

from bkuser.apis.web.tenant_organization.serializers import (
TenantsListOutputSLZ,
TenantsRetrieveOutputSLZ,
TenantUpdateInputSLZ,
)
from bkuser.apis.web.organization.serializers import TenantListOutputSLZ
from bkuser.apis.web.tenant.serializers import TenantRetrieveOutputSLZ, TenantUpdateInputSLZ
from bkuser.apps.tenant.models import Tenant
from bkuser.biz.tenant import (
TenantDepartmentHandler,
TenantEditableBaseInfo,
TenantFeatureFlag,
TenantHandler,
)
from bkuser.common.error_codes import error_codes
from bkuser.common.views import ExcludePatchAPIViewMixin

logger = logging.getLogger(__name__)


class TenantsListApi(generics.ListAPIView):
class TenantListApi(generics.ListAPIView):
pagination_class = None
queryset = Tenant.objects.all()
serializer_class = TenantsListOutputSLZ
serializer_class = TenantListOutputSLZ

def _get_tenant_id(self) -> str:
# TODO 根据登录用户获取租户
return self.queryset.first().id
return self.request.user.get_property("tenant_id")

def get_serializer_context(self):
return {"current_tenant_id": self._get_tenant_id()}

def get_queryset(self):
tenant_id = self._get_tenant_id()
# TODO 协同数据源, 以租户的形式展示, 如何获取?
return Tenant.objects.filter(id__in=[tenant_id])
tenant_ids = list(self.queryset.values_list("id", flat=True))
tenant_root_departments_map = TenantDepartmentHandler.get_tenant_root_departments_by_id(
tenant_ids, self._get_tenant_id()
)
return {"tenant_root_departments_map": tenant_root_departments_map}

@swagger_auto_schema(
operation_description="租户列表",
responses={status.HTTP_200_OK: TenantsListOutputSLZ(many=True)},
responses={status.HTTP_200_OK: TenantListOutputSLZ(many=True)},
)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
Expand All @@ -58,24 +55,18 @@ def get(self, request, *args, **kwargs):
class TenantRetrieveUpdateApi(ExcludePatchAPIViewMixin, generics.RetrieveUpdateAPIView):
queryset = Tenant.objects.all()
pagination_class = None
serializer_class = TenantsRetrieveOutputSLZ
serializer_class = TenantRetrieveOutputSLZ
lookup_url_kwarg = "id"

def _get_tenant_id(self) -> str:
# TODO 根据当前租户获取租户ID
return self.queryset.first().id
return self.request.user.get_property("tenant_id")

def get_serializer_context(self):
# 根据当前登录的租户用户,获取租户ID
tenant_id = self._get_tenant_id()
# NOTE 因协同数据源,而展示的租户,不返回管理员
return {
"tenant_manager_map": TenantHandler.get_tenant_manager_map(tenant_ids=[tenant_id]),
}
return {"current_tenant_id": self._get_tenant_id()}

@swagger_auto_schema(
operation_description="单个租户详情",
responses={status.HTTP_200_OK: TenantsRetrieveOutputSLZ()},
responses={status.HTTP_200_OK: TenantRetrieveOutputSLZ()},
)
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
Expand All @@ -91,14 +82,13 @@ def put(self, request, *args, **kwargs):
data = slz.validated_data

instance = self.get_object()
# NOTE 因协同数据源,而展示的租户,不返回管理员
# NOTE 因协同数据源而展示的租户,非当前租户, 无权限做更新操作
if self._get_tenant_id() != instance.id:
return Response
raise error_codes.NO_PERMISSION

should_updated_info = TenantEditableBaseInfo(
name=data["name"], logo=data.get("logo") or "", feature_flags=TenantFeatureFlag(**data["feature_flags"])
name=data["name"], logo=data["logo"] or "", feature_flags=TenantFeatureFlag(**data["feature_flags"])
)

TenantHandler.update_with_managers(instance.id, should_updated_info, data["manager_ids"])

return Response()
20 changes: 9 additions & 11 deletions src/bk-user/bkuser/apis/web/tenant/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from bkuser.apps.data_source.models import DataSourceUser
from bkuser.apps.tenant.models import Tenant, TenantUser
from bkuser.biz.data_source import DataSourceSimpleInfo
from bkuser.biz.tenant import TenantUserWithInheritedInfo
from bkuser.biz.tenant import TenantHandler, TenantUserWithInheritedInfo
from bkuser.biz.validators import validate_tenant_id


Expand Down Expand Up @@ -100,7 +100,7 @@ def get_data_sources(self, obj: Tenant) -> List[Dict]:

class TenantUpdateInputSLZ(serializers.Serializer):
name = serializers.CharField(help_text="租户名称")
logo = serializers.CharField(help_text="租户 Logo", required=False)
logo = serializers.CharField(help_text="租户 Logo", required=False, default=settings.DEFAULT_TENANT_LOGO)
manager_ids = serializers.ListField(child=serializers.CharField(), help_text="租户用户 ID 列表", allow_empty=False)
feature_flags = TenantFeatureFlagSLZ(help_text="租户特性集")

Expand All @@ -125,16 +125,14 @@ class TenantRetrieveOutputSLZ(serializers.Serializer):

@swagger_serializer_method(serializer_or_field=TenantRetrieveManagerOutputSchema(many=True))
def get_managers(self, obj: Tenant) -> List[Dict]:
tenant_manager_map: Dict[str, List[TenantUserWithInheritedInfo]] = self.context["tenant_manager_map"]
managers = tenant_manager_map.get(obj.id) or []
# 根据当前登录的租户用户,获取租户ID
# NOTE 因协同数据源而展示的租户,不返回管理员
if obj.id != self.context["current_tenant_id"]:
return []
managers = TenantHandler.retrieve_tenant_manager(obj.id)
return [
{
"id": i.id,
**i.data_source_user.model_dump(
include={"username", "full_name", "email", "phone", "phone_country_code"}
),
}
for i in managers
{"id": manager.id, **manager.data_source_user.model_dump(include={"username", "full_name"})}
for manager in managers
]

def get_logo(self, obj: Tenant) -> str:
Expand Down
106 changes: 0 additions & 106 deletions src/bk-user/bkuser/apis/web/tenant_organization/serializers.py

This file was deleted.

2 changes: 1 addition & 1 deletion src/bk-user/bkuser/apis/web/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
path("basic/", include("bkuser.apis.web.basic.urls")),
# 租户
path("tenants/", include("bkuser.apis.web.tenant.urls")),
path("tenant-organization-tree/", include("bkuser.apis.web.tenant_organization.urls")),
path("tenant-organization/", include("bkuser.apis.web.organization.urls")),
]
56 changes: 27 additions & 29 deletions src/bk-user/bkuser/biz/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
from pydantic import BaseModel

from bkuser.apps.data_source.models import DataSource, DataSourceDepartment, DataSourceDepartmentRelation
from bkuser.common.error_codes import error_codes


class DataSourceDepartmentInfo(BaseModel):
class DataSourceDepartmentInfoWithChildren(BaseModel):
id: int
name: str
data_source_id: int
children: list
full_name: str
children: List[int]


class DataSourceSimpleInfo(BaseModel):
Expand All @@ -48,33 +45,34 @@ def get_data_source_map_by_owner(

return data

@staticmethod
def get_data_sources_by_tenant(tenant_ids: List[str]) -> Dict[str, List[int]]:
# 当前属于租户的数据源
tenant_data_source_map: Dict = {}
data_sources = DataSource.objects.filter(owner_tenant_id__in=tenant_ids).values("id", "owner_tenant_id")
for item in data_sources:
tenant_id = item["owner_tenant_id"]
if tenant_id in tenant_data_source_map:
tenant_data_source_map[tenant_id].append(item["id"])
else:
tenant_data_source_map[tenant_id] = [item["id"]]
# TODO 协同数据源获取
return tenant_data_source_map


class DataSourceDepartmentHandler:
@staticmethod
def retrieve_department(department_id: int) -> DataSourceDepartmentInfo:
def get_department_info_by_id(department_ids: List[int]) -> Dict[int, DataSourceDepartmentInfoWithChildren]:
"""
获取单个部门信息
获取部门基础信息
"""
try:
# 生成组织架构路径
parent_ids = (
DataSourceDepartmentRelation.objects.get(id=department_id)
.get_ancestors(include_self=True)
.values_list("id", flat=True)
departments = DataSourceDepartment.objects.filter(id__in=department_ids)
departments_map: Dict = {}
for item in departments:
children = DataSourceDepartmentRelation.objects.get(department=item).get_children()
departments_map[item.id] = DataSourceDepartmentInfoWithChildren(
id=item.id,
name=item.name,
children=list(children.values_list("department_id", flat=True)),
)
parents = DataSourceDepartment.objects.filter(id__in=parent_ids).values_list("name", flat=True)
full_name = "/".join(list(parents))
# 构建基础信息
department = DataSourceDepartment.objects.get(id=department_id)
base_info = {
"id": department.id,
"name": department.name,
"full_name": full_name,
"data_source_id": department.data_source_id,
"children": DataSourceDepartmentRelation.objects.filter(parent_id=department.id).values(
"id", flat=True
),
}
return DataSourceDepartmentInfo(**base_info)
except DataSourceDepartment.DoesNotExist:
raise error_codes.OBJECT_NOT_FOUND
return departments_map
Loading

0 comments on commit 7fc371c

Please sign in to comment.