Skip to content

Commit

Permalink
minor: merge tencent/ft_tenant into general_data_source_sync_plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
narasux committed Oct 16, 2023
2 parents 65f66d0 + edbf45a commit 8319beb
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 12 deletions.
41 changes: 40 additions & 1 deletion src/bk-user/bkuser/apis/web/data_source/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import logging
from typing import Any, Dict, List

from django.conf import settings
from django.core.files.uploadedfile import UploadedFile
from django.utils.translation import gettext_lazy as _
from drf_yasg.utils import swagger_serializer_method
from pydantic import ValidationError as PDValidationError
Expand All @@ -20,8 +22,10 @@
from bkuser.apps.data_source.constants import FieldMappingOperation
from bkuser.apps.data_source.models import DataSource, DataSourcePlugin
from bkuser.apps.tenant.models import TenantUserCustomField, UserBuiltinField
from bkuser.biz.data_source_plugin import DefaultPluginConfigProvider
from bkuser.plugins.base import get_plugin_cfg_cls, is_plugin_exists
from bkuser.plugins.constants import DataSourcePluginEnum
from bkuser.plugins.local.models import PasswordRuleConfig
from bkuser.plugins.models import DataSourceSyncConfig
from bkuser.utils.pydantic import stringify_pydantic_error

Expand Down Expand Up @@ -174,7 +178,7 @@ class DataSourceRetrieveOutputSLZ(serializers.Serializer):


class DataSourceUpdateInputSLZ(serializers.Serializer):
name = serializers.CharField(help_text="数据源名称")
name = serializers.CharField(help_text="数据源名称", max_length=128)
plugin_config = serializers.JSONField(help_text="数据源插件配置")
field_mapping = serializers.ListField(
help_text="用户字段映射", child=DataSourceFieldMappingSLZ(), allow_empty=True, required=False, default=list
Expand Down Expand Up @@ -267,13 +271,48 @@ class DataSourceTestConnectionOutputSLZ(serializers.Serializer):
extras = serializers.JSONField(help_text="额外信息")


class DataSourceRandomPasswordInputSLZ(serializers.Serializer):
"""生成随机密码"""

password_rule_config = serializers.JSONField(help_text="密码规则配置", required=False)

def validate(self, attrs):
passwd_rule_cfg = attrs.get("password_rule_config")
if passwd_rule_cfg:
try:
attrs["password_rule"] = PasswordRuleConfig(**passwd_rule_cfg).to_rule()
except PDValidationError as e:
raise ValidationError(_("密码规则配置不合法: {}").format(stringify_pydantic_error(e)))
else:
attrs["password_rule"] = (
DefaultPluginConfigProvider().get(DataSourcePluginEnum.LOCAL).password_rule.to_rule() # type: ignore
)

return attrs


class DataSourceRandomPasswordOutputSLZ(serializers.Serializer):
"""生成随机密码结果"""

password = serializers.CharField(help_text="密码")


class LocalDataSourceImportInputSLZ(serializers.Serializer):
"""本地数据源导入"""

file = serializers.FileField(help_text="数据源用户信息文件(Excel 格式)")
overwrite = serializers.BooleanField(help_text="允许对同名用户覆盖更新", default=False)
incremental = serializers.BooleanField(help_text="是否使用增量同步", default=False)

def validate_file(self, file: UploadedFile) -> UploadedFile:
if not file.name.endswith(".xlsx"):
raise ValidationError(_("待导入文件必须为 Excel 格式"))

if file.size > settings.MAX_USER_DATA_FILE_SIZE * 1024 * 1024:
raise ValidationError(_("待导入文件大小不得超过 {} M").format(settings.MAX_USER_DATA_FILE_SIZE))

return file


class DataSourceImportOrSyncOutputSLZ(serializers.Serializer):
"""数据源导入/同步结果"""
Expand Down
4 changes: 3 additions & 1 deletion src/bk-user/bkuser/apis/web/data_source/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
),
# 数据源创建/获取列表
path("", views.DataSourceListCreateApi.as_view(), name="data_source.list_create"),
# 连通性测试
# 数据源随机密码获取
path("random-passwords/", views.DataSourceRandomPasswordApi.as_view(), name="data_source.random_passwords"),
# 数据源连通性测试
path(
"test-connection/",
views.DataSourceTestConnectionApi.as_view(),
Expand Down
19 changes: 19 additions & 0 deletions src/bk-user/bkuser/apis/web/data_source/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
DataSourceImportOrSyncOutputSLZ,
DataSourcePluginDefaultConfigOutputSLZ,
DataSourcePluginOutputSLZ,
DataSourceRandomPasswordInputSLZ,
DataSourceRandomPasswordOutputSLZ,
DataSourceRetrieveOutputSLZ,
DataSourceSearchInputSLZ,
DataSourceSearchOutputSLZ,
Expand All @@ -43,6 +45,7 @@
from bkuser.biz.data_source_plugin import DefaultPluginConfigProvider
from bkuser.biz.exporters import DataSourceUserExporter
from bkuser.common.error_codes import error_codes
from bkuser.common.passwd import PasswordGenerator
from bkuser.common.response import convert_workbook_to_response
from bkuser.common.views import ExcludePatchAPIViewMixin, ExcludePutAPIViewMixin
from bkuser.plugins.base import get_plugin_cfg_schema_map, get_plugin_cls
Expand Down Expand Up @@ -192,6 +195,22 @@ def put(self, request, *args, **kwargs):
return Response(status=status.HTTP_204_NO_CONTENT)


class DataSourceRandomPasswordApi(generics.CreateAPIView):
@swagger_auto_schema(
tags=["data_source"],
operation_description="生成数据源用户随机密码",
request_body=DataSourceRandomPasswordInputSLZ(),
responses={status.HTTP_200_OK: DataSourceRandomPasswordOutputSLZ()},
)
def post(self, request, *args, **kwargs):
slz = DataSourceRandomPasswordInputSLZ(data=request.data)
slz.is_valid(raise_exception=True)
data = slz.validated_data

passwd = PasswordGenerator(data["password_rule"]).generate()
return Response(DataSourceRandomPasswordOutputSLZ(instance={"password": passwd}).data)


class DataSourceTestConnectionApi(generics.CreateAPIView):
"""数据源连通性测试"""

Expand Down
4 changes: 1 addition & 3 deletions src/bk-user/bkuser/apps/data_source/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
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 re

from blue_krill.data_types.enum import EnumField, StructuredEnum
from django.utils.translation import gettext_lazy as _

DATA_SOURCE_USERNAME_REGEX = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]{2,31}")
from bkuser.plugins.local.constants import USERNAME_REGEX as DATA_SOURCE_USERNAME_REGEX # noqa: F401


class DataSourceStatus(str, StructuredEnum):
Expand Down
2 changes: 1 addition & 1 deletion src/bk-user/bkuser/biz/data_source_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _get_default_local_plugin_config(self) -> BaseModel:
not_continuous_letter=False,
not_continuous_digit=False,
not_repeated_symbol=False,
valid_time=365,
valid_time=90,
max_retries=3,
lock_time=60 * 60,
),
Expand Down
14 changes: 9 additions & 5 deletions src/bk-user/bkuser/biz/exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def export(self) -> Workbook:
)
)

self._set_all_cells_to_text_format()
return self.workbook

def _load_template(self):
Expand All @@ -83,11 +84,8 @@ def _load_template(self):
self.sheet.alignment = Alignment(wrapText=True)
# 补充租户用户自定义字段
self._update_sheet_custom_field_columns()

# 将单元格设置为纯文本模式,防止出现类型转换
for columns in self.sheet.columns:
for cell in columns:
cell.number_format = FORMAT_TEXT
# 将所有单元格设置为文本格式
self._set_all_cells_to_text_format()

def _update_sheet_custom_field_columns(self):
"""在模版中补充自定义字段"""
Expand All @@ -107,6 +105,12 @@ def _update_sheet_custom_field_columns(self):
# 设置默认列宽
self.sheet.column_dimensions[self._gen_sheet_col_idx(col_idx)].width = self.default_column_width

def _set_all_cells_to_text_format(self):
# 将单元格设置为纯文本模式,防止出现类型转换
for columns in self.sheet.columns:
for cell in columns:
cell.number_format = FORMAT_TEXT

@staticmethod
def _gen_sheet_col_idx(idx: int) -> str:
"""
Expand Down
4 changes: 4 additions & 0 deletions src/bk-user/bkuser/plugins/local/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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 re

from blue_krill.data_types.enum import EnumField, StructuredEnum
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -36,6 +37,9 @@
# 保留的历史密码上限
MAX_RESERVED_PREVIOUS_PASSWORD_COUNT = 5

# 数据源用户名规则
USERNAME_REGEX = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]{2,31}")


class PasswordGenerateMethod(str, StructuredEnum):
"""密码生成方式"""
Expand Down
4 changes: 3 additions & 1 deletion src/bk-user/bkuser/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,9 @@
# zxcvbn 会对密码进行总体强度评估(score [0, 4]),建议限制不能使用评分低于 3 的密码
MIN_ZXCVBN_PASSWORD_SCORE = env.int("MIN_ZXCVBN_PASSWORD_SCORE", 3)

# 数据导出配置
# 数据导入/导出配置
# 导入文件大小限制,单位为 MB
MAX_USER_DATA_FILE_SIZE = env.int("MAX_USER_DATA_FILE_SIZE", 10)
# 导出文件名称前缀
EXPORT_EXCEL_FILENAME_PREFIX = "bk_user_export"
# 成员,组织信息导出模板
Expand Down

0 comments on commit 8319beb

Please sign in to comment.